summaryrefslogtreecommitdiffstats
path: root/qmake/generators/win32
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commit38be0d13830efd2d98281c645c3a60afe05ffece (patch)
tree6ea73f3ec77f7d153333779883e8120f82820abe /qmake/generators/win32
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'qmake/generators/win32')
-rw-r--r--qmake/generators/win32/borland_bmake.cpp175
-rw-r--r--qmake/generators/win32/borland_bmake.h68
-rw-r--r--qmake/generators/win32/mingw_make.cpp516
-rw-r--r--qmake/generators/win32/mingw_make.h88
-rw-r--r--qmake/generators/win32/msbuild_objectmodel.cpp1940
-rw-r--r--qmake/generators/win32/msbuild_objectmodel.h192
-rw-r--r--qmake/generators/win32/msvc_nmake.cpp361
-rw-r--r--qmake/generators/win32/msvc_nmake.h78
-rw-r--r--qmake/generators/win32/msvc_objectmodel.cpp2909
-rw-r--r--qmake/generators/win32/msvc_objectmodel.h1141
-rw-r--r--qmake/generators/win32/msvc_vcproj.cpp1569
-rw-r--r--qmake/generators/win32/msvc_vcproj.h151
-rw-r--r--qmake/generators/win32/msvc_vcxproj.cpp74
-rw-r--r--qmake/generators/win32/msvc_vcxproj.h70
-rw-r--r--qmake/generators/win32/winmakefile.cpp895
-rw-r--r--qmake/generators/win32/winmakefile.h96
16 files changed, 10323 insertions, 0 deletions
diff --git a/qmake/generators/win32/borland_bmake.cpp b/qmake/generators/win32/borland_bmake.cpp
new file mode 100644
index 0000000000..585a0f4982
--- /dev/null
+++ b/qmake/generators/win32/borland_bmake.cpp
@@ -0,0 +1,175 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the qmake application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "borland_bmake.h"
+#include "option.h"
+#include <qdir.h>
+#include <qregexp.h>
+#include <time.h>
+
+QT_BEGIN_NAMESPACE
+
+BorlandMakefileGenerator::BorlandMakefileGenerator() : Win32MakefileGenerator(), init_flag(false)
+{
+
+}
+
+bool
+BorlandMakefileGenerator::writeMakefile(QTextStream &t)
+{
+ writeHeader(t);
+ if(!project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty()) {
+ QStringList &qut = project->values("QMAKE_EXTRA_TARGETS");
+ for(QStringList::ConstIterator it = qut.begin(); it != qut.end(); ++it)
+ t << *it << " ";
+ t << "all first clean:" << "\n\t"
+ << "@echo \"Some of the required modules ("
+ << var("QMAKE_FAILED_REQUIREMENTS") << ") are not available.\"" << "\n\t"
+ << "@echo \"Skipped.\"" << endl << endl;
+ return true;
+ }
+
+ if(project->first("TEMPLATE") == "app" ||
+ project->first("TEMPLATE") == "lib") {
+ writeBorlandParts(t);
+ return MakefileGenerator::writeMakefile(t);
+ }
+ else if(project->first("TEMPLATE") == "subdirs") {
+ writeSubDirs(t);
+ return true;
+ }
+ return false;
+}
+
+void
+BorlandMakefileGenerator::writeBorlandParts(QTextStream &t)
+{
+ t << "!if !$d(BCB)" << endl;
+ t << "BCB = $(MAKEDIR)\\.." << endl;
+ t << "!endif" << endl << endl;
+
+ writeStandardParts(t);
+}
+
+void
+BorlandMakefileGenerator::init()
+{
+ if(init_flag)
+ return;
+ init_flag = true;
+
+ /* this should probably not be here, but I'm using it to wrap the .t files */
+ if (project->first("TEMPLATE") == "app") {
+ project->values("QMAKE_APP_FLAG").append("1");
+ } else if(project->first("TEMPLATE") == "lib"){
+ project->values("QMAKE_LIB_FLAG").append("1");
+ } else if(project->first("TEMPLATE") == "subdirs") {
+ MakefileGenerator::init();
+ if(project->isEmpty("QMAKE_COPY_FILE"))
+ project->values("QMAKE_COPY_FILE").append("$(COPY)");
+ if(project->isEmpty("QMAKE_COPY_DIR"))
+ project->values("QMAKE_COPY_DIR").append("xcopy /s /q /y /i");
+ if(project->isEmpty("QMAKE_INSTALL_FILE"))
+ project->values("QMAKE_INSTALL_FILE").append("$(COPY_FILE)");
+ if(project->isEmpty("QMAKE_INSTALL_PROGRAM"))
+ project->values("QMAKE_INSTALL_PROGRAM").append("$(COPY_FILE)");
+ if(project->isEmpty("QMAKE_INSTALL_DIR"))
+ project->values("QMAKE_INSTALL_DIR").append("$(COPY_DIR)");
+ if(project->values("MAKEFILE").isEmpty())
+ project->values("MAKEFILE").append("Makefile");
+ return;
+ }
+
+ processVars();
+
+ project->values("QMAKE_LIBS") += project->values("LIBS");
+
+ MakefileGenerator::init();
+
+ if (project->isActiveConfig("dll") || !project->values("QMAKE_APP_FLAG").isEmpty()) {
+ // bcc does not generate a .tds file for static libs
+ QString tdsPostfix;
+ if (!project->values("VERSION").isEmpty())
+ tdsPostfix = project->first("TARGET_VERSION_EXT");
+ tdsPostfix += ".tds";
+ project->values("QMAKE_CLEAN").append(project->first("DESTDIR") + project->first("TARGET") + tdsPostfix);
+ }
+}
+
+void BorlandMakefileGenerator::writeBuildRulesPart(QTextStream &t)
+{
+ t << "first: all" << endl;
+ t << "all: " << fileFixify(Option::output.fileName()) << " " << varGlue("ALL_DEPS"," "," "," ") << " $(DESTDIR_TARGET)" << endl << endl;
+ t << "$(DESTDIR_TARGET): " << var("PRE_TARGETDEPS") << " $(OBJECTS) " << var("POST_TARGETDEPS");
+ if(!project->isEmpty("QMAKE_PRE_LINK"))
+ t << "\n\t" <<var("QMAKE_PRE_LINK");
+ if(project->isActiveConfig("staticlib")) {
+ t << "\n\t-$(DEL_FILE) $(DESTDIR_TARGET)"
+ << "\n\t" << "$(LIB) $(DESTDIR_TARGET) @&&|" << " \n+"
+ << project->values("OBJECTS").join(" \\\n+") << " \\\n+"
+ << project->values("OBJMOC").join(" \\\n+");
+ } else {
+ t << "\n\t" << "$(LINK) @&&|" << "\n\t"
+ << "$(LFLAGS) $(OBJECTS) $(OBJMOC),$(DESTDIR_TARGET),,$(LIBS),$(DEF_FILE),$(RES_FILE)";
+ }
+ t << endl << "|";
+ if(!project->isEmpty("QMAKE_POST_LINK"))
+ t << "\n\t" <<var("QMAKE_POST_LINK");
+ t << endl;
+}
+
+void BorlandMakefileGenerator::writeCleanParts(QTextStream &t)
+{
+ t << "clean: "
+ << varGlue("OBJECTS","\n\t-$(DEL_FILE) ","\n\t-$(DEL_FILE) ","")
+ << varGlue("QMAKE_CLEAN","\n\t-$(DEL_FILE) ","\n\t-$(DEL_FILE) ","\n")
+ << varGlue("CLEAN_FILES","\n\t-$(DEL_FILE) ","\n\t-$(DEL_FILE) ","\n");
+
+ if(!project->isEmpty("IMAGES"))
+ t << varGlue("QMAKE_IMAGE_COLLECTION", "\n\t-$(DEL_FILE) ", "\n\t-$(DEL_FILE) ", "");
+ t << endl;
+
+ t << "distclean: clean"
+ << "\n\t-$(DEL_FILE) $(DESTDIR_TARGET)"
+ << endl << endl;
+}
+
+QT_END_NAMESPACE
diff --git a/qmake/generators/win32/borland_bmake.h b/qmake/generators/win32/borland_bmake.h
new file mode 100644
index 0000000000..7a2734f5e3
--- /dev/null
+++ b/qmake/generators/win32/borland_bmake.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the qmake application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BORLAND_BMAKE_H
+#define BORLAND_BMAKE_H
+
+#include "winmakefile.h"
+
+QT_BEGIN_NAMESPACE
+
+class BorlandMakefileGenerator : public Win32MakefileGenerator
+{
+ bool init_flag;
+ void writeBorlandParts(QTextStream &);
+ void writeBuildRulesPart(QTextStream &t);
+ void writeCleanParts(QTextStream &t);
+ bool writeMakefile(QTextStream &);
+ void init();
+
+public:
+ BorlandMakefileGenerator();
+ ~BorlandMakefileGenerator();
+};
+
+inline BorlandMakefileGenerator::~BorlandMakefileGenerator()
+{ }
+
+QT_END_NAMESPACE
+
+#endif // BORLAND_BMAKE_H
diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp
new file mode 100644
index 0000000000..462920e06c
--- /dev/null
+++ b/qmake/generators/win32/mingw_make.cpp
@@ -0,0 +1,516 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the qmake application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mingw_make.h"
+#include "option.h"
+#include "meta.h"
+#include <qregexp.h>
+#include <qdir.h>
+#include <stdlib.h>
+#include <time.h>
+
+QT_BEGIN_NAMESPACE
+
+MingwMakefileGenerator::MingwMakefileGenerator() : Win32MakefileGenerator(), init_flag(false)
+{
+ if (Option::shellPath.isEmpty())
+ quote = "\"";
+ else
+ quote = "'";
+}
+
+bool MingwMakefileGenerator::isWindowsShell() const
+{
+#ifdef Q_OS_WIN
+ return Option::shellPath.isEmpty();
+#else
+ return Win32MakefileGenerator::isWindowsShell();
+#endif
+}
+
+QString MingwMakefileGenerator::escapeDependencyPath(const QString &path) const
+{
+ QString ret = path;
+ ret.remove('\"');
+ ret.replace('\\', "/");
+ ret.replace(' ', "\\ ");
+ return ret;
+}
+
+QString MingwMakefileGenerator::getLibTarget()
+{
+ return QString("lib" + project->first("TARGET") + project->first("TARGET_VERSION_EXT") + ".a");
+}
+
+bool MingwMakefileGenerator::findLibraries()
+{
+ return findLibraries("QMAKE_LIBS") && findLibraries("QMAKE_LIBS_PRIVATE");
+}
+
+bool MingwMakefileGenerator::findLibraries(const QString &where)
+{
+ QStringList &l = project->values(where);
+
+ QList<QMakeLocalFileName> dirs;
+ {
+ QStringList &libpaths = project->values("QMAKE_LIBDIR");
+ for(QStringList::Iterator libpathit = libpaths.begin();
+ libpathit != libpaths.end(); ++libpathit)
+ dirs.append(QMakeLocalFileName((*libpathit)));
+ }
+
+ QStringList::Iterator it = l.begin();
+ while (it != l.end()) {
+ if ((*it).startsWith("-l")) {
+ QString steam = (*it).mid(2), out;
+ QString suffix;
+ if (!project->isEmpty("QMAKE_" + steam.toUpper() + "_SUFFIX"))
+ suffix = project->first("QMAKE_" + steam.toUpper() + "_SUFFIX");
+ for (QList<QMakeLocalFileName>::Iterator dir_it = dirs.begin(); dir_it != dirs.end(); ++dir_it) {
+ QString extension;
+ int ver = findHighestVersion((*dir_it).local(), steam, "dll.a|a");
+ if (ver != -1)
+ extension += QString::number(ver);
+ extension += suffix;
+ if(QMakeMetaInfo::libExists((*dir_it).local() + Option::dir_sep + steam) ||
+ exists((*dir_it).local() + Option::dir_sep + steam + extension + ".a") ||
+ exists((*dir_it).local() + Option::dir_sep + steam + extension + ".dll.a")) {
+ out = (*it) + extension;
+ break;
+ }
+ }
+ if (!out.isEmpty()) // We assume if it never finds it that its correct
+ (*it) = out;
+ } else if((*it).startsWith("-L")) {
+ dirs.append(QMakeLocalFileName((*it).mid(2)));
+ }
+
+ ++it;
+ }
+ return true;
+}
+
+bool MingwMakefileGenerator::writeMakefile(QTextStream &t)
+{
+ writeHeader(t);
+ if(!project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty()) {
+ t << "all clean:" << "\n\t"
+ << "@echo \"Some of the required modules ("
+ << var("QMAKE_FAILED_REQUIREMENTS") << ") are not available.\"" << "\n\t"
+ << "@echo \"Skipped.\"" << endl << endl;
+ writeMakeQmake(t);
+ return true;
+ }
+
+ if(project->first("TEMPLATE") == "app" ||
+ project->first("TEMPLATE") == "lib") {
+ if(project->isActiveConfig("create_pc") && project->first("TEMPLATE") == "lib")
+ writePkgConfigFile();
+
+ if(Option::mkfile::do_stub_makefile) {
+ t << "QMAKE = " << var("QMAKE_QMAKE") << endl;
+ QStringList &qut = project->values("QMAKE_EXTRA_TARGETS");
+ for(QStringList::ConstIterator it = qut.begin(); it != qut.end(); ++it)
+ t << *it << " ";
+ t << "first all clean install distclean uninstall: qmake" << endl
+ << "qmake_all:" << endl;
+ writeMakeQmake(t);
+ if(project->isEmpty("QMAKE_NOFORCE"))
+ t << "FORCE:" << endl << endl;
+ return true;
+ }
+ writeMingwParts(t);
+ return MakefileGenerator::writeMakefile(t);
+ }
+ else if(project->first("TEMPLATE") == "subdirs") {
+ writeSubDirs(t);
+ return true;
+ }
+ return false;
+ }
+
+void createLdObjectScriptFile(const QString &fileName, const QStringList &objList)
+{
+ QString filePath = Option::output_dir + QDir::separator() + fileName;
+ QFile file(filePath);
+ if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ QTextStream t(&file);
+ t << "INPUT(" << endl;
+ for (QStringList::ConstIterator it = objList.constBegin(); it != objList.constEnd(); ++it) {
+ if (QDir::isRelativePath(*it))
+ t << "./" << *it << endl;
+ else
+ t << *it << endl;
+ }
+ t << ");" << endl;
+ t.flush();
+ file.close();
+ }
+}
+
+void createArObjectScriptFile(const QString &fileName, const QString &target, const QStringList &objList)
+{
+ QString filePath = Option::output_dir + QDir::separator() + fileName;
+ QFile file(filePath);
+ if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ QTextStream t(&file);
+ t << "CREATE " << target << endl;
+ for (QStringList::ConstIterator it = objList.constBegin(); it != objList.constEnd(); ++it) {
+ t << "ADDMOD " << *it << endl;
+ }
+ t << "SAVE" << endl;
+ t.flush();
+ file.close();
+ }
+}
+
+void createRvctObjectScriptFile(const QString &fileName, const QStringList &objList)
+{
+ QString filePath = Option::output_dir + QDir::separator() + fileName;
+ QFile file(filePath);
+ if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ QTextStream t(&file);
+ for (QStringList::ConstIterator it = objList.constBegin(); it != objList.constEnd(); ++it) {
+ if (QDir::isRelativePath(*it))
+ t << "./" << *it << endl;
+ else
+ t << *it << endl;
+ }
+ t.flush();
+ file.close();
+ }
+}
+
+void MingwMakefileGenerator::writeMingwParts(QTextStream &t)
+{
+ if (!project->isEmpty("QMAKE_SYMBIAN_SHLIB")) {
+ t << "vpath %.dso " << project->values("QMAKE_LIBDIR").join(";") << endl;
+ t << "vpath %.lib " << project->values("QMAKE_LIBDIR").join(";") << endl;
+ t << "\n\n";
+ }
+
+ writeStandardParts(t);
+
+ if (!preCompHeaderOut.isEmpty()) {
+ QString header = project->first("PRECOMPILED_HEADER");
+ QString cHeader = preCompHeaderOut + Option::dir_sep + "c";
+ t << escapeDependencyPath(cHeader) << ": " << escapeDependencyPath(header) << " "
+ << escapeDependencyPaths(findDependencies(header)).join(" \\\n\t\t")
+ << "\n\t" << mkdir_p_asstring(preCompHeaderOut)
+ << "\n\t" << "$(CC) -x c-header -c $(CFLAGS) $(INCPATH) -o " << cHeader << " " << header
+ << endl << endl;
+ QString cppHeader = preCompHeaderOut + Option::dir_sep + "c++";
+ t << escapeDependencyPath(cppHeader) << ": " << escapeDependencyPath(header) << " "
+ << escapeDependencyPaths(findDependencies(header)).join(" \\\n\t\t")
+ << "\n\t" << mkdir_p_asstring(preCompHeaderOut)
+ << "\n\t" << "$(CXX) -x c++-header -c $(CXXFLAGS) $(INCPATH) -o " << cppHeader << " " << header
+ << endl << endl;
+ }
+}
+
+void MingwMakefileGenerator::init()
+{
+ if(init_flag)
+ return;
+ init_flag = true;
+
+ /* this should probably not be here, but I'm using it to wrap the .t files */
+ if(project->first("TEMPLATE") == "app")
+ project->values("QMAKE_APP_FLAG").append("1");
+ else if(project->first("TEMPLATE") == "lib")
+ project->values("QMAKE_LIB_FLAG").append("1");
+ else if(project->first("TEMPLATE") == "subdirs") {
+ MakefileGenerator::init();
+ if(project->isEmpty("QMAKE_COPY_FILE"))
+ project->values("QMAKE_COPY_FILE").append("$(COPY)");
+ if(project->isEmpty("QMAKE_COPY_DIR"))
+ project->values("QMAKE_COPY_DIR").append("xcopy /s /q /y /i");
+ if(project->isEmpty("QMAKE_INSTALL_FILE"))
+ project->values("QMAKE_INSTALL_FILE").append("$(COPY_FILE)");
+ if(project->isEmpty("QMAKE_INSTALL_PROGRAM"))
+ project->values("QMAKE_INSTALL_PROGRAM").append("$(COPY_FILE)");
+ if(project->isEmpty("QMAKE_INSTALL_DIR"))
+ project->values("QMAKE_INSTALL_DIR").append("$(COPY_DIR)");
+ if(project->values("MAKEFILE").isEmpty())
+ project->values("MAKEFILE").append("Makefile");
+ return;
+ }
+
+ project->values("TARGET_PRL").append(project->first("TARGET"));
+
+ processVars();
+
+ if (!project->values("RES_FILE").isEmpty()) {
+ project->values("QMAKE_LIBS") += escapeFilePaths(project->values("RES_FILE"));
+ }
+
+ // LIBS defined in Profile comes first for gcc
+ project->values("QMAKE_LIBS") += escapeFilePaths(project->values("LIBS"));
+ project->values("QMAKE_LIBS_PRIVATE") += escapeFilePaths(project->values("LIBS_PRIVATE"));
+
+ QString targetfilename = project->values("TARGET").first();
+ QStringList &configs = project->values("CONFIG");
+
+ if(project->isActiveConfig("qt_dll"))
+ if(configs.indexOf("qt") == -1)
+ configs.append("qt");
+
+ if(project->isActiveConfig("dll") && project->values("QMAKE_SYMBIAN_SHLIB").isEmpty()) {
+ QString destDir = "";
+ if(!project->first("DESTDIR").isEmpty())
+ destDir = Option::fixPathToTargetOS(project->first("DESTDIR") + Option::dir_sep, false, false);
+ project->values("MINGW_IMPORT_LIB").prepend(destDir + "lib" + project->first("TARGET")
+ + project->first("TARGET_VERSION_EXT") + ".a");
+ project->values("QMAKE_LFLAGS").append(QString("-Wl,--out-implib,") + project->first("MINGW_IMPORT_LIB"));
+ }
+
+ if(!project->values("DEF_FILE").isEmpty() && project->values("QMAKE_SYMBIAN_SHLIB").isEmpty()) {
+ QString defFileName = fileFixify(project->values("DEF_FILE")).first();
+ project->values("QMAKE_LFLAGS").append(QString("-Wl,") + escapeFilePath(defFileName));
+ }
+
+ MakefileGenerator::init();
+
+ // precomp
+ if (!project->first("PRECOMPILED_HEADER").isEmpty()
+ && project->isActiveConfig("precompile_header")) {
+ QString preCompHeader = var("PRECOMPILED_DIR")
+ + QFileInfo(project->first("PRECOMPILED_HEADER")).fileName();
+ preCompHeaderOut = preCompHeader + ".gch";
+ project->values("QMAKE_CLEAN").append(preCompHeaderOut + Option::dir_sep + "c");
+ project->values("QMAKE_CLEAN").append(preCompHeaderOut + Option::dir_sep + "c++");
+
+ project->values("QMAKE_RUN_CC").clear();
+ project->values("QMAKE_RUN_CC").append("$(CC) -c -include " + preCompHeader +
+ " $(CFLAGS) $(INCPATH) -o $obj $src");
+ project->values("QMAKE_RUN_CC_IMP").clear();
+ project->values("QMAKE_RUN_CC_IMP").append("$(CC) -c -include " + preCompHeader +
+ " $(CFLAGS) $(INCPATH) -o $@ $<");
+ project->values("QMAKE_RUN_CXX").clear();
+ project->values("QMAKE_RUN_CXX").append("$(CXX) -c -include " + preCompHeader +
+ " $(CXXFLAGS) $(INCPATH) -o $obj $src");
+ project->values("QMAKE_RUN_CXX_IMP").clear();
+ project->values("QMAKE_RUN_CXX_IMP").append("$(CXX) -c -include " + preCompHeader +
+ " $(CXXFLAGS) $(INCPATH) -o $@ $<");
+ }
+
+ if(project->isActiveConfig("dll")) {
+ project->values("QMAKE_CLEAN").append(project->first("MINGW_IMPORT_LIB"));
+ }
+}
+
+void MingwMakefileGenerator::fixTargetExt()
+{
+ if (project->isActiveConfig("staticlib") && project->first("TEMPLATE") == "lib") {
+ project->values("QMAKE_LFLAGS").append("-static");
+ }
+ Win32MakefileGenerator::fixTargetExt();
+}
+
+void MingwMakefileGenerator::writeIncPart(QTextStream &t)
+{
+ t << "INCPATH = ";
+
+ QStringList &incs = project->values("INCLUDEPATH");
+ for(QStringList::Iterator incit = incs.begin(); incit != incs.end(); ++incit) {
+ QString inc = (*incit);
+ inc.replace(QRegExp("\\\\$"), "");
+ inc.replace(QRegExp("\""), "");
+ t << "-I" << quote << inc << quote << " ";
+ }
+ t << "-I" << quote << specdir() << quote
+ << endl;
+}
+
+void MingwMakefileGenerator::writeLibsPart(QTextStream &t)
+{
+ if(project->isActiveConfig("staticlib") && project->first("TEMPLATE") == "lib") {
+ t << "LIB = " << var("QMAKE_LIB") << endl;
+ } else {
+ t << "LINK = " << var("QMAKE_LINK") << endl;
+ t << "LFLAGS = " << var("QMAKE_LFLAGS") << endl;
+ t << "LIBS = ";
+ if(!project->values("QMAKE_LIBDIR").isEmpty())
+ writeLibDirPart(t);
+ if (project->isActiveConfig("rvct_linker")) {
+ t << var("QMAKE_LIBS") << ' '
+ << var("QMAKE_LIBS_PRIVATE") << endl;
+ } else {
+ t << var("QMAKE_LIBS").replace(QRegExp("(\\slib|^lib)")," -l") << ' '
+ << var("QMAKE_LIBS_PRIVATE").replace(QRegExp("(\\slib|^lib)")," -l") << endl;
+ }
+ }
+}
+
+void MingwMakefileGenerator::writeLibDirPart(QTextStream &t)
+{
+ QStringList libDirs = project->values("QMAKE_LIBDIR");
+ QString libArg = QString::fromLatin1("-L");
+ if (project->isActiveConfig("rvct_linker"))
+ libArg = QString::fromLatin1("--userlibpath ");
+ for (int i = 0; i < libDirs.size(); ++i) {
+ libDirs[i].remove("\"");
+ if (libDirs[i].endsWith("\\"))
+ libDirs[i].chop(1);
+ }
+ t << valGlue(libDirs, libArg+quote, quote+" "+libArg+quote, quote) << " ";
+}
+
+void MingwMakefileGenerator::writeObjectsPart(QTextStream &t)
+{
+ if (project->values("OBJECTS").count() < var("QMAKE_LINK_OBJECT_MAX").toInt()) {
+ objectsLinkLine = "$(OBJECTS)";
+ } else if (project->isActiveConfig("staticlib") && project->first("TEMPLATE") == "lib") {
+ QString ar_script_file = var("QMAKE_LINK_OBJECT_SCRIPT") + "." + var("TARGET");
+ if (!var("BUILD_NAME").isEmpty()) {
+ ar_script_file += "." + var("BUILD_NAME");
+ }
+ // QMAKE_LIB is used for win32, including mingw, whereas QMAKE_AR is used on Unix.
+ if (project->isActiveConfig("rvct_linker")) {
+ createRvctObjectScriptFile(ar_script_file, project->values("OBJECTS"));
+ QString ar_cmd = project->values("QMAKE_LIB").join(" ");
+ if (ar_cmd.isEmpty())
+ ar_cmd = "armar --create";
+ objectsLinkLine = ar_cmd + " " + var("DEST_TARGET") + " --via " + ar_script_file;
+ } else {
+ // Strip off any options since the ar commands will be read from file.
+ QString ar_cmd = var("QMAKE_LIB").section(" ", 0, 0);;
+ if (ar_cmd.isEmpty())
+ ar_cmd = "ar";
+ createArObjectScriptFile(ar_script_file, var("DEST_TARGET"), project->values("OBJECTS"));
+ objectsLinkLine = ar_cmd + " -M < " + ar_script_file;
+ }
+ } else {
+ QString ld_script_file = var("QMAKE_LINK_OBJECT_SCRIPT") + "." + var("TARGET");
+ if (!var("BUILD_NAME").isEmpty()) {
+ ld_script_file += "." + var("BUILD_NAME");
+ }
+ if (project->isActiveConfig("rvct_linker")) {
+ createRvctObjectScriptFile(ld_script_file, project->values("OBJECTS"));
+ objectsLinkLine = QString::fromLatin1("--via ") + ld_script_file;
+ } else {
+ createLdObjectScriptFile(ld_script_file, project->values("OBJECTS"));
+ objectsLinkLine = ld_script_file;
+ }
+ }
+ Win32MakefileGenerator::writeObjectsPart(t);
+}
+
+void MingwMakefileGenerator::writeBuildRulesPart(QTextStream &t)
+{
+ t << "first: all" << endl;
+ t << "all: " << escapeDependencyPath(fileFixify(Option::output.fileName())) << " " << valGlue(escapeDependencyPaths(project->values("ALL_DEPS"))," "," "," ") << " $(DESTDIR_TARGET)" << endl << endl;
+ t << "$(DESTDIR_TARGET): " << var("PRE_TARGETDEPS") << " $(OBJECTS) " << var("POST_TARGETDEPS");
+ if(!project->isEmpty("QMAKE_PRE_LINK"))
+ t << "\n\t" <<var("QMAKE_PRE_LINK");
+ if(project->isActiveConfig("staticlib") && project->first("TEMPLATE") == "lib") {
+ if (project->values("OBJECTS").count() < var("QMAKE_LINK_OBJECT_MAX").toInt()) {
+ t << "\n\t" << "$(LIB) $(DESTDIR_TARGET) " << objectsLinkLine << " " ;
+ } else {
+ t << "\n\t" << objectsLinkLine << " " ;
+ }
+ } else {
+ t << "\n\t" << "$(LINK) $(LFLAGS) -o $(DESTDIR_TARGET) " << objectsLinkLine << " " << " $(LIBS)";
+ }
+ if(!project->isEmpty("QMAKE_POST_LINK"))
+ t << "\n\t" <<var("QMAKE_POST_LINK");
+ t << endl;
+}
+
+void MingwMakefileGenerator::writeRcFilePart(QTextStream &t)
+{
+ const QString rc_file = fileFixify(project->first("RC_FILE"));
+
+ QString incPathStr = fileInfo(rc_file).path();
+ if (incPathStr != "." && QDir::isRelativePath(incPathStr))
+ incPathStr.prepend("./");
+
+ if (!rc_file.isEmpty()) {
+ t << escapeDependencyPath(var("RES_FILE")) << ": " << rc_file << "\n\t"
+ << var("QMAKE_RC") << " -i " << rc_file << " -o " << var("RES_FILE")
+ << " --include-dir=" << incPathStr << " $(DEFINES)" << endl << endl;
+ }
+}
+
+void MingwMakefileGenerator::processPrlVariable(const QString &var, const QStringList &l)
+{
+ if (var == "QMAKE_PRL_LIBS") {
+ QString where = "QMAKE_LIBS";
+ if (!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS"))
+ where = project->first("QMAKE_INTERNAL_PRL_LIBS");
+ QStringList &out = project->values(where);
+ for (QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
+ out.removeAll((*it));
+ out.append((*it));
+ }
+ } else {
+ Win32MakefileGenerator::processPrlVariable(var, l);
+ }
+}
+
+QStringList &MingwMakefileGenerator::findDependencies(const QString &file)
+{
+ QStringList &aList = MakefileGenerator::findDependencies(file);
+ // Note: The QMAKE_IMAGE_COLLECTION file have all images
+ // as dependency, so don't add precompiled header then
+ if (file == project->first("QMAKE_IMAGE_COLLECTION")
+ || preCompHeaderOut.isEmpty())
+ return aList;
+ for (QStringList::Iterator it = Option::c_ext.begin(); it != Option::c_ext.end(); ++it) {
+ if (file.endsWith(*it)) {
+ QString cHeader = preCompHeaderOut + Option::dir_sep + "c";
+ if (!aList.contains(cHeader))
+ aList += cHeader;
+ break;
+ }
+ }
+ for (QStringList::Iterator it = Option::cpp_ext.begin(); it != Option::cpp_ext.end(); ++it) {
+ if (file.endsWith(*it)) {
+ QString cppHeader = preCompHeaderOut + Option::dir_sep + "c++";
+ if (!aList.contains(cppHeader))
+ aList += cppHeader;
+ break;
+ }
+ }
+ return aList;
+}
+
+QT_END_NAMESPACE
diff --git a/qmake/generators/win32/mingw_make.h b/qmake/generators/win32/mingw_make.h
new file mode 100644
index 0000000000..5bc9c7b3b4
--- /dev/null
+++ b/qmake/generators/win32/mingw_make.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the qmake application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MINGW_MAKE_H
+#define MINGW_MAKE_H
+
+#include "winmakefile.h"
+
+QT_BEGIN_NAMESPACE
+
+class MingwMakefileGenerator : public Win32MakefileGenerator
+{
+public:
+ MingwMakefileGenerator();
+ ~MingwMakefileGenerator();
+protected:
+ QString escapeDependencyPath(const QString &path) const;
+ QString getLibTarget();
+ bool writeMakefile(QTextStream &);
+ void init();
+private:
+ bool isWindowsShell() const;
+ void writeMingwParts(QTextStream &);
+ void writeIncPart(QTextStream &t);
+ void writeLibsPart(QTextStream &t);
+ void writeLibDirPart(QTextStream &t);
+ void writeObjectsPart(QTextStream &t);
+ void writeBuildRulesPart(QTextStream &t);
+ void writeRcFilePart(QTextStream &t);
+ void processPrlVariable(const QString &var, const QStringList &l);
+
+ QStringList &findDependencies(const QString &file);
+
+ QString preCompHeaderOut;
+
+ virtual bool findLibraries();
+ bool findLibraries(const QString &where);
+ void fixTargetExt();
+
+ bool init_flag;
+ QString objectsLinkLine;
+ QString quote;
+};
+
+inline MingwMakefileGenerator::~MingwMakefileGenerator()
+{ }
+
+QT_END_NAMESPACE
+
+#endif // MINGW_MAKE_H
diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp
new file mode 100644
index 0000000000..d4d2400146
--- /dev/null
+++ b/qmake/generators/win32/msbuild_objectmodel.cpp
@@ -0,0 +1,1940 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the qmake application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "msvc_objectmodel.h"
+#include "msbuild_objectmodel.h"
+#include "msvc_vcproj.h"
+#include "msvc_vcxproj.h"
+#include <qstringlist.h>
+#include <qfileinfo.h>
+
+QT_BEGIN_NAMESPACE
+
+// XML Tags ---------------------------------------------------------
+const char _CLCompile[] = "ClCompile";
+const char _ItemGroup[] = "ItemGroup";
+const char _Link[] = "Link";
+const char _Midl[] = "Midl";
+const char _ResourceCompile[] = "ResourceCompile";
+
+// XML Properties ---------------------------------------------------
+const char _AddModuleNamesToAssembly[] = "AddModuleNamesToAssembly";
+const char _AdditionalDependencies[] = "AdditionalDependencies";
+const char _AdditionalIncludeDirectories[] = "AdditionalIncludeDirectories";
+const char _AdditionalLibraryDirectories[] = "AdditionalLibraryDirectories";
+const char _AdditionalManifestDependencies[] = "AdditionalManifestDependencies";
+const char _AdditionalOptions[] = "AdditionalOptions";
+const char _AdditionalUsingDirectories[] = "AdditionalUsingDirectories";
+const char _AllowIsolation[] = "AllowIsolation";
+const char _AlwaysAppend[] = "AlwaysAppend";
+const char _ApplicationConfigurationMode[] = "ApplicationConfigurationMode";
+const char _AssemblerListingLocation[] = "AssemblerListingLocation";
+const char _AssemblerOutput[] = "AssemblerOutput";
+const char _AssemblyDebug[] = "AssemblyDebug";
+const char _AssemblyLinkResource[] = "AssemblyLinkResource";
+const char _ATLMinimizesCRunTimeLibraryUsage[] = "ATLMinimizesCRunTimeLibraryUsage";
+const char _BaseAddress[] = "BaseAddress";
+const char _BasicRuntimeChecks[] = "BasicRuntimeChecks";
+const char _BrowseInformation[] = "BrowseInformation";
+const char _BrowseInformationFile[] = "BrowseInformationFile";
+const char _BufferSecurityCheck[] = "BufferSecurityCheck";
+const char _BuildBrowserInformation[] = "BuildBrowserInformation";
+const char _CallingConvention[] = "CallingConvention";
+const char _CharacterSet[] = "CharacterSet";
+const char _ClientStubFile[] = "ClientStubFile";
+const char _CLRImageType[] = "CLRImageType";
+const char _CLRSupportLastError[] = "CLRSupportLastError";
+const char _CLRThreadAttribute[] = "CLRThreadAttribute";
+const char _CLRUnmanagedCodeCheck[] = "CLRUnmanagedCodeCheck";
+const char _Command[] = "Command";
+const char _CompileAs[] = "CompileAs";
+const char _CompileAsManaged[] = "CompileAsManaged";
+const char _ConfigurationType[] = "ConfigurationType";
+const char _CPreprocessOptions[] = "CPreprocessOptions";
+const char _CreateHotpatchableImage[] = "CreateHotpatchableImage";
+const char _CreateHotPatchableImage[] = "CreateHotPatchableImage";
+const char _Culture[] = "Culture";
+const char _DataExecutionPrevention[] = "DataExecutionPrevention";
+const char _DebugInformationFormat[] = "DebugInformationFormat";
+const char _DefaultCharType[] = "DefaultCharType";
+const char _DelayLoadDLLs[] = "DelayLoadDLLs";
+const char _DelaySign[] = "DelaySign";
+const char _DeleteExtensionsOnClean[] = "DeleteExtensionsOnClean";
+const char _DisableLanguageExtensions[] = "DisableLanguageExtensions";
+const char _DisableSpecificWarnings[] = "DisableSpecificWarnings";
+const char _DisplayLibrary[] = "DisplayLibrary";
+const char _DLLDataFileName[] = "DLLDataFileName";
+const char _EmbedManagedResourceFile[] = "EmbedManagedResourceFile";
+const char _EnableCOMDATFolding[] = "EnableCOMDATFolding";
+const char _EnableUAC[] = "EnableUAC";
+const char _EnableErrorChecks[] = "EnableErrorChecks";
+const char _EnableEnhancedInstructionSet[] = "EnableEnhancedInstructionSet";
+const char _EnableFiberSafeOptimizations[] = "EnableFiberSafeOptimizations";
+const char _EnablePREfast[] = "EnablePREfast";
+const char _EntryPointSymbol[] = "EntryPointSymbol";
+const char _ErrorCheckAllocations[] = "ErrorCheckAllocations";
+const char _ErrorCheckBounds[] = "ErrorCheckBounds";
+const char _ErrorCheckEnumRange[] = "ErrorCheckEnumRange";
+const char _ErrorCheckRefPointers[] = "ErrorCheckRefPointers";
+const char _ErrorCheckStubData[] = "ErrorCheckStubData";
+const char _ErrorReporting[] = "ErrorReporting";
+const char _ExceptionHandling[] = "ExceptionHandling";
+const char _ExpandAttributedSource[] = "ExpandAttributedSource";
+const char _ExportNamedFunctions[] = "ExportNamedFunctions";
+const char _FavorSizeOrSpeed[] = "FavorSizeOrSpeed";
+const char _FloatingPointModel[] = "FloatingPointModel";
+const char _FloatingPointExceptions[] = "FloatingPointExceptions";
+const char _ForceConformanceInForLoopScope[] = "ForceConformanceInForLoopScope";
+const char _ForceSymbolReferences[] = "ForceSymbolReferences";
+const char _ForcedIncludeFiles[] = "ForcedIncludeFiles";
+const char _ForcedUsingFiles[] = "ForcedUsingFiles";
+const char _FunctionLevelLinking[] = "FunctionLevelLinking";
+const char _FunctionOrder[] = "FunctionOrder";
+const char _GenerateClientFiles[] = "GenerateClientFiles";
+const char _GenerateDebugInformation[] = "GenerateDebugInformation";
+const char _GenerateManifest[] = "GenerateManifest";
+const char _GenerateMapFile[] = "GenerateMapFile";
+const char _GenerateServerFiles[] = "GenerateServerFiles";
+const char _GenerateStublessProxies[] = "GenerateStublessProxies";
+const char _GenerateTypeLibrary[] = "GenerateTypeLibrary";
+const char _GenerateXMLDocumentationFiles[] = "GenerateXMLDocumentationFiles";
+const char _HeaderFileName[] = "HeaderFileName";
+const char _HeapCommitSize[] = "HeapCommitSize";
+const char _HeapReserveSize[] = "HeapReserveSize";
+const char _IgnoreAllDefaultLibraries[] = "IgnoreAllDefaultLibraries";
+const char _IgnoreEmbeddedIDL[] = "IgnoreEmbeddedIDL";
+const char _IgnoreImportLibrary[] = "IgnoreImportLibrary";
+const char _IgnoreSpecificDefaultLibraries[] = "IgnoreSpecificDefaultLibraries";
+const char _IgnoreStandardIncludePath[] = "IgnoreStandardIncludePath";
+const char _ImportLibrary[] = "ImportLibrary";
+const char _InlineFunctionExpansion[] = "InlineFunctionExpansion";
+const char _IntrinsicFunctions[] = "IntrinsicFunctions";
+const char _InterfaceIdentifierFileName[] = "InterfaceIdentifierFileName";
+const char _IntermediateDirectory[] = "IntermediateDirectory";
+const char _KeyContainer[] = "KeyContainer";
+const char _KeyFile[] = "KeyFile";
+const char _LargeAddressAware[] = "LargeAddressAware";
+const char _LinkDLL[] = "LinkDLL";
+const char _LinkErrorReporting[] = "LinkErrorReporting";
+const char _LinkIncremental[] = "LinkIncremental";
+const char _LinkStatus[] = "LinkStatus";
+const char _LinkTimeCodeGeneration[] = "LinkTimeCodeGeneration";
+const char _LocaleID[] = "LocaleID";
+const char _ManifestFile[] = "ManifestFile";
+const char _MapExports[] = "MapExports";
+const char _MapFileName[] = "MapFileName";
+const char _MergedIDLBaseFileName[] = "MergedIDLBaseFileName";
+const char _MergeSections[] = "MergeSections";
+const char _Message[] = "Message";
+const char _MidlCommandFile[] = "MidlCommandFile";
+const char _MinimalRebuild[] = "MinimalRebuild";
+const char _MkTypLibCompatible[] = "MkTypLibCompatible";
+const char _ModuleDefinitionFile[] = "ModuleDefinitionFile";
+const char _MultiProcessorCompilation[] = "MultiProcessorCompilation";
+const char _Name[] = "Name";
+const char _NoEntryPoint[] = "NoEntryPoint";
+const char _NullTerminateStrings[] = "NullTerminateStrings";
+const char _ObjectFiles[] = "ObjectFiles";
+const char _ObjectFileName[] = "ObjectFileName";
+const char _OmitDefaultLibName[] = "OmitDefaultLibName";
+const char _OmitFramePointers[] = "OmitFramePointers";
+const char _OpenMPSupport[] = "OpenMPSupport";
+const char _Optimization[] = "Optimization";
+const char _OptimizeReferences[] = "OptimizeReferences";
+const char _OutputDirectory[] = "OutputDirectory";
+const char _OutputFile[] = "OutputFile";
+const char _PrecompiledHeader[] = "PrecompiledHeader";
+const char _PrecompiledHeaderFile[] = "PrecompiledHeaderFile";
+const char _PrecompiledHeaderOutputFile[] = "PrecompiledHeaderOutputFile";
+const char _PreprocessorDefinitions[] = "PreprocessorDefinitions";
+const char _PreprocessKeepComments[] = "PreprocessKeepComments";
+const char _PreprocessOutputPath[] = "PreprocessOutputPath";
+const char _PreprocessSuppressLineNumbers[] = "PreprocessSuppressLineNumbers";
+const char _PreprocessToFile[] = "PreprocessToFile";
+const char _PreventDllBinding[] = "PreventDllBinding";
+const char _PrimaryOutput[] = "PrimaryOutput";
+const char _ProcessorNumber[] = "ProcessorNumber";
+const char _ProgramDatabase[] = "ProgramDatabase";
+const char _ProgramDataBaseFileName[] = "ProgramDataBaseFileName";
+const char _ProgramDatabaseFile[] = "ProgramDatabaseFile";
+const char _ProxyFileName[] = "ProxyFileName";
+const char _RandomizedBaseAddress[] = "RandomizedBaseAddress";
+const char _RedirectOutputAndErrors[] = "RedirectOutputAndErrors";
+const char _RegisterOutput[] = "RegisterOutput";
+const char _RemoveObjects[] = "RemoveObjects";
+const char _ResourceOutputFileName[] = "ResourceOutputFileName";
+const char _RuntimeLibrary[] = "RuntimeLibrary";
+const char _RuntimeTypeInfo[] = "RuntimeTypeInfo";
+const char _SectionAlignment[] = "SectionAlignment";
+const char _ServerStubFile[] = "ServerStubFile";
+const char _SetChecksum[] = "SetChecksum";
+const char _ShowIncludes[] = "ShowIncludes";
+const char _ShowProgress[] = "ShowProgress";
+const char _SmallerTypeCheck[] = "SmallerTypeCheck";
+const char _StackCommitSize[] = "StackCommitSize";
+const char _StackReserveSize[] = "StackReserveSize";
+const char _StringPooling[] = "StringPooling";
+const char _StripPrivateSymbols[] = "StripPrivateSymbols";
+const char _StructMemberAlignment[] = "StructMemberAlignment";
+const char _SubSystem[] = "SubSystem";
+const char _SupportNobindOfDelayLoadedDLL[] = "SupportNobindOfDelayLoadedDLL";
+const char _SupportUnloadOfDelayLoadedDLL[] = "SupportUnloadOfDelayLoadedDLL";
+const char _SuppressCompilerWarnings[] = "SuppressCompilerWarnings";
+const char _SuppressStartupBanner[] = "SuppressStartupBanner";
+const char _SwapRunFromCD[] = "SwapRunFromCD";
+const char _SwapRunFromNet[] = "SwapRunFromNet";
+const char _TargetEnvironment[] = "TargetEnvironment";
+const char _TargetMachine[] = "TargetMachine";
+const char _TerminalServerAware[] = "TerminalServerAware";
+const char _TrackerLogDirectory[] = "TrackerLogDirectory";
+const char _TreatLibWarningAsErrors[] = "TreatLibWarningAsErrors";
+const char _TreatLinkerWarningAsErrors[] = "TreatLinkerWarningAsErrors";
+const char _TreatSpecificWarningsAsErrors[] = "TreatSpecificWarningsAsErrors";
+const char _TreatWarningAsError[] = "TreatWarningAsError";
+const char _TreatWChar_tAsBuiltInType[] = "TreatWChar_tAsBuiltInType";
+const char _TurnOffAssemblyGeneration[] = "TurnOffAssemblyGeneration";
+const char _TypeLibFormat[] = "TypeLibFormat";
+const char _TypeLibraryFile[] = "TypeLibraryFile";
+const char _TypeLibraryName[] = "TypeLibraryName";
+const char _TypeLibraryResourceID[] = "TypeLibraryResourceID";
+const char _UACExecutionLevel[] = "UACExecutionLevel";
+const char _UACUIAccess[] = "UACUIAccess";
+const char _UndefineAllPreprocessorDefinitions[]= "UndefineAllPreprocessorDefinitions";
+const char _UndefinePreprocessorDefinitions[] = "UndefinePreprocessorDefinitions";
+const char _UseFullPaths[] = "UseFullPaths";
+const char _UseOfATL[] = "UseOfATL";
+const char _UseOfMfc[] = "UseOfMfc";
+const char _UseUnicodeForAssemblerListing[] = "UseUnicodeForAssemblerListing";
+const char _ValidateAllParameters[] = "ValidateAllParameters";
+const char _VCCustomBuildTool[] = "VCCustomBuildTool";
+const char _Verbose[] = "Verbose";
+const char _Version[] = "Version";
+const char _WarnAsError[] = "WarnAsError";
+const char _WarningLevel[] = "WarningLevel";
+const char _WholeProgramOptimization[] = "WholeProgramOptimization";
+const char _XMLDocumentationFileName[] = "XMLDocumentationFileName";
+
+
+// XmlOutput stream functions ------------------------------
+inline XmlOutput::xml_output attrTagT(const char *name, const triState v)
+{
+ if(v == unset)
+ return noxml();
+ return tagValue(name, (v == _True ? "true" : "false"));
+}
+
+inline XmlOutput::xml_output attrTagL(const char *name, qint64 v)
+{
+ return tagValue(name, QString::number(v));
+}
+
+/*ifNot version*/
+inline XmlOutput::xml_output attrTagL(const char *name, qint64 v, qint64 ifn)
+{
+ if (v == ifn)
+ return noxml();
+ return tagValue(name, QString::number(v));
+}
+
+inline XmlOutput::xml_output attrTagS(const char *name, const QString &v)
+{
+ if(v.isEmpty())
+ return noxml();
+ return tagValue(name, v);
+}
+
+inline XmlOutput::xml_output attrTagX(const char *name, const QStringList &v, const char *s = ",")
+{
+ if(v.isEmpty())
+ return noxml();
+ QStringList temp = v;
+ temp.append(QString("%(%1)").arg(name));
+ return tagValue(name, temp.join(s));
+}
+
+inline XmlOutput::xml_output valueTagX(const QStringList &v, const char *s = " ")
+{
+ if(v.isEmpty())
+ return noxml();
+ return valueTag(v.join(s));
+}
+
+inline XmlOutput::xml_output valueTagDefX(const QStringList &v, const QString &tagName, const char *s = " ")
+{
+ if(v.isEmpty())
+ return noxml();
+ QStringList temp = v;
+ temp.append(QString("%(%1)").arg(tagName));
+ return valueTag(temp.join(s));
+}
+
+inline XmlOutput::xml_output valueTagT( const triState v)
+{
+ if(v == unset)
+ return noxml();
+ return valueTag(v == _True ? "true" : "false");
+}
+
+static QString vcxCommandSeparator()
+{
+ // MSBuild puts the contents of the custom commands into a batch file and calls it.
+ // As we want every sub-command to be error-checked (as is done by makefile-based
+ // backends), we insert the checks ourselves, using the undocumented jump target.
+ static QString cmdSep =
+ QLatin1String("&#x000D;&#x000A;if errorlevel 1 goto VCEnd&#x000D;&#x000A;");
+ return cmdSep;
+}
+
+// Tree file generation ---------------------------------------------
+void XTreeNode::generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &tagName, VCProject &tool, const QString &filter) {
+
+ if (children.size()) {
+ // Filter
+ QString tempFilterName;
+ ChildrenMap::ConstIterator it, end = children.constEnd();
+ if (!tagName.isEmpty()) {
+ tempFilterName.append(filter);
+ tempFilterName.append("\\");
+ tempFilterName.append(tagName);
+ xmlFilter << tag(_ItemGroup);
+ xmlFilter << tag("Filter")
+ << attrTag("Include", tempFilterName)
+ << closetag();
+ xmlFilter << closetag();
+ }
+ // First round, do nested filters
+ for (it = children.constBegin(); it != end; ++it)
+ if ((*it)->children.size())
+ {
+ if ( !tempFilterName.isEmpty() )
+ (*it)->generateXML(xml, xmlFilter, it.key(), tool, tempFilterName);
+ else
+ (*it)->generateXML(xml, xmlFilter, it.key(), tool, filter);
+ }
+ // Second round, do leafs
+ for (it = children.constBegin(); it != end; ++it)
+ if (!(*it)->children.size())
+ {
+ if ( !tempFilterName.isEmpty() )
+ (*it)->generateXML(xml, xmlFilter, it.key(), tool, tempFilterName);
+ else
+ (*it)->generateXML(xml, xmlFilter, it.key(), tool, filter);
+ }
+ } else {
+ // Leaf
+ xml << tag(_ItemGroup);
+ xmlFilter << tag(_ItemGroup);
+ VCXProjectWriter::outputFileConfigs(tool, xml, xmlFilter, info, filter);
+ xmlFilter << closetag();
+ xml << closetag();
+ }
+}
+
+// Flat file generation ---------------------------------------------
+void XFlatNode::generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &/*tagName*/, VCProject &tool, const QString &filter) {
+ if (children.size()) {
+ ChildrenMapFlat::ConstIterator it = children.constBegin();
+ ChildrenMapFlat::ConstIterator end = children.constEnd();
+ xml << tag(_ItemGroup);
+ xmlFilter << tag(_ItemGroup);
+ for (; it != end; ++it) {
+ VCXProjectWriter::outputFileConfigs(tool, xml, xmlFilter, (*it), filter);
+ }
+ xml << closetag();
+ xmlFilter << closetag();
+ }
+}
+
+void VCXProjectWriter::write(XmlOutput &xml, VCProjectSingleConfig &tool)
+{
+ xml.setIndentString(" ");
+
+ xml << decl("1.0", "utf-8")
+ << tag("Project")
+ << attrTag("DefaultTargets","Build")
+ << attrTag("ToolsVersion", "4.0")
+ << attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003")
+ << tag("ItemGroup")
+ << attrTag("Label", "ProjectConfigurations");
+
+ xml << tag("ProjectConfiguration")
+ << attrTag("Include" , tool.Configuration.Name)
+ << tagValue("Configuration", tool.Configuration.ConfigurationName)
+ << tagValue("Platform", tool.PlatformName)
+ << closetag();
+
+ xml << closetag()
+ << tag("PropertyGroup")
+ << attrTag("Label", "Globals")
+ << tagValue("ProjectGuid", tool.ProjectGUID)
+ << tagValue("RootNamespace", tool.Name)
+ << tagValue("Keyword", tool.Keyword)
+ << closetag();
+
+ // config part.
+ xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.Default.props");
+
+ write(xml, tool.Configuration);
+
+ xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props");
+
+ // Extension settings
+ xml << tag("ImportGroup")
+ << attrTag("Label", "ExtensionSettings")
+ << closetag();
+
+ // PropertySheets
+ xml << tag("ImportGroup")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name))
+ << attrTag("Label", "PropertySheets");
+
+ xml << tag("Import")
+ << attrTag("Project", "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props")
+ << attrTag("Condition", "exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')")
+ << closetag()
+ << closetag();
+
+
+ // UserMacros
+ xml << tag("PropertyGroup")
+ << attrTag("Label", "UserMacros")
+ << closetag();
+
+ xml << tag("PropertyGroup");
+
+ if ( !tool.Configuration.OutputDirectory.isEmpty() ) {
+ xml<< tag("OutDir")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name))
+ << valueTag(tool.Configuration.OutputDirectory);
+ }
+ if ( !tool.Configuration.IntermediateDirectory.isEmpty() ) {
+ xml<< tag("IntDir")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name))
+ << valueTag(tool.Configuration.IntermediateDirectory);
+ }
+ if ( !tool.Configuration.PrimaryOutput.isEmpty() ) {
+ xml<< tag("TargetName")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name))
+ << valueTag(tool.Configuration.PrimaryOutput);
+ }
+
+ if ( tool.Configuration.linker.IgnoreImportLibrary != unset) {
+ xml<< tag("IgnoreImportLibrary")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name))
+ << valueTagT(tool.Configuration.linker.IgnoreImportLibrary);
+ }
+
+ if ( tool.Configuration.linker.LinkIncremental != linkIncrementalDefault) {
+ const triState ts = (tool.Configuration.linker.LinkIncremental == linkIncrementalYes ? _True : _False);
+ xml<< tag("LinkIncremental")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name))
+ << valueTagT(ts);
+ }
+
+ if ( tool.Configuration.preBuild.ExcludedFromBuild != unset )
+ {
+ xml<< tag("PreBuildEventUseInBuild")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name))
+ << valueTagT(!tool.Configuration.preBuild.ExcludedFromBuild);
+ }
+
+ if ( tool.Configuration.preLink.ExcludedFromBuild != unset )
+ {
+ xml<< tag("PreLinkEventUseInBuild")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name))
+ << valueTagT(!tool.Configuration.preLink.ExcludedFromBuild);
+ }
+
+ if ( tool.Configuration.postBuild.ExcludedFromBuild != unset )
+ {
+ xml<< tag("PostBuildEventUseInBuild")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name))
+ << valueTagT(!tool.Configuration.postBuild.ExcludedFromBuild);
+ }
+ xml << closetag();
+
+ xml << tag("ItemDefinitionGroup")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name));
+
+ // ClCompile
+ write(xml, tool.Configuration.compiler);
+
+ // Link
+ write(xml, tool.Configuration.linker);
+
+ // Midl
+ write(xml, tool.Configuration.idl);
+
+ // ResourceCompiler
+ write(xml, tool.Configuration.resource);
+
+ // Post build event
+ if ( tool.Configuration.postBuild.ExcludedFromBuild != unset )
+ write(xml, tool.Configuration.postBuild);
+
+ // Pre build event
+ if ( tool.Configuration.preBuild.ExcludedFromBuild != unset )
+ write(xml, tool.Configuration.preBuild);
+
+ // Pre link event
+ if ( tool.Configuration.preLink.ExcludedFromBuild != unset )
+ write(xml, tool.Configuration.preLink);
+
+ xml << closetag();
+
+ QFile filterFile;
+ filterFile.setFileName(Option::output.fileName().append(".filters"));
+ filterFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate);
+ QTextStream ts(&filterFile);
+ XmlOutput xmlFilter(ts, XmlOutput::NoConversion);
+
+ xmlFilter.setIndentString(" ");
+
+ xmlFilter << decl("1.0", "utf-8")
+ << tag("Project")
+ << attrTag("ToolsVersion", "4.0")
+ << attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
+
+ xmlFilter << tag("ItemGroup");
+
+ VCProject tempProj;
+ tempProj.SingleProjects += tool;
+
+ addFilters(tempProj, xmlFilter, "Form Files");
+ addFilters(tempProj, xmlFilter, "Generated Files");
+ addFilters(tempProj, xmlFilter, "Header Files");
+ addFilters(tempProj, xmlFilter, "LexYacc Files");
+ addFilters(tempProj, xmlFilter, "Resource Files");
+ addFilters(tempProj, xmlFilter, "Source Files");
+ addFilters(tempProj, xmlFilter, "Translation Files");
+ xmlFilter << closetag();
+
+ outputFilter(tempProj, xml, xmlFilter, "Source Files");
+ outputFilter(tempProj, xml, xmlFilter, "Header Files");
+ outputFilter(tempProj, xml, xmlFilter, "Generated Files");
+ outputFilter(tempProj, xml, xmlFilter, "LexYacc Files");
+ outputFilter(tempProj, xml, xmlFilter, "Translation Files");
+ outputFilter(tempProj, xml, xmlFilter, "Form Files");
+ outputFilter(tempProj, xml, xmlFilter, "Resource Files");
+
+ for (int x = 0; x < tempProj.ExtraCompilers.count(); ++x) {
+ outputFilter(tempProj, xml, xmlFilter, tempProj.ExtraCompilers.at(x));
+ }
+
+ xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets");
+
+ xml << tag("ImportGroup")
+ << attrTag("Label", "ExtensionTargets")
+ << closetag();
+}
+
+void VCXProjectWriter::write(XmlOutput &xml, VCProject &tool)
+{
+ if (tool.SingleProjects.count() == 0) {
+ warn_msg(WarnLogic, "Generator: .NET: no single project in merge project, no output");
+ return;
+ }
+
+ xml.setIndentString(" ");
+
+ xml << decl("1.0", "utf-8")
+ << tag("Project")
+ << attrTag("DefaultTargets","Build")
+ << attrTag("ToolsVersion", "4.0")
+ << attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003")
+ << tag("ItemGroup")
+ << attrTag("Label", "ProjectConfigurations");
+
+ for (int i = 0; i < tool.SingleProjects.count(); ++i) {
+ xml << tag("ProjectConfiguration")
+ << attrTag("Include" , tool.SingleProjects.at(i).Configuration.Name)
+ << tagValue("Configuration", tool.SingleProjects.at(i).Configuration.ConfigurationName)
+ << tagValue("Platform", tool.SingleProjects.at(i).PlatformName)
+ << closetag();
+ }
+
+ xml << closetag()
+ << tag("PropertyGroup")
+ << attrTag("Label", "Globals")
+ << tagValue("ProjectGuid", tool.ProjectGUID)
+ << tagValue("RootNamespace", tool.Name)
+ << tagValue("Keyword", tool.Keyword)
+ << closetag();
+
+ // config part.
+ xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.Default.props");
+ for (int i = 0; i < tool.SingleProjects.count(); ++i)
+ write(xml, tool.SingleProjects.at(i).Configuration);
+ xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props");
+
+ // Extension settings
+ xml << tag("ImportGroup")
+ << attrTag("Label", "ExtensionSettings")
+ << closetag();
+
+ // PropertySheets
+ for (int i = 0; i < tool.SingleProjects.count(); ++i) {
+ xml << tag("ImportGroup")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name))
+ << attrTag("Label", "PropertySheets");
+
+ xml << tag("Import")
+ << attrTag("Project", "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props")
+ << attrTag("Condition", "exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')")
+ << closetag()
+ << closetag();
+ }
+
+ // UserMacros
+ xml << tag("PropertyGroup")
+ << attrTag("Label", "UserMacros")
+ << closetag();
+
+ xml << tag("PropertyGroup");
+ for (int i = 0; i < tool.SingleProjects.count(); ++i) {
+
+ if ( !tool.SingleProjects.at(i).Configuration.OutputDirectory.isEmpty() ) {
+ xml << tag("OutDir")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name))
+ << valueTag(tool.SingleProjects.at(i).Configuration.OutputDirectory);
+ }
+ if ( !tool.SingleProjects.at(i).Configuration.IntermediateDirectory.isEmpty() ) {
+ xml << tag("IntDir")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name))
+ << valueTag(tool.SingleProjects.at(i).Configuration.IntermediateDirectory);
+ }
+ if ( !tool.SingleProjects.at(i).Configuration.PrimaryOutput.isEmpty() ) {
+ xml << tag("TargetName")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name))
+ << valueTag(tool.SingleProjects.at(i).Configuration.PrimaryOutput);
+ }
+
+ if ( tool.SingleProjects.at(i).Configuration.linker.IgnoreImportLibrary != unset) {
+ xml << tag("IgnoreImportLibrary")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name))
+ << valueTagT(tool.SingleProjects.at(i).Configuration.linker.IgnoreImportLibrary);
+ }
+
+ if ( tool.SingleProjects.at(i).Configuration.linker.LinkIncremental != unset) {
+ const triState ts = (tool.SingleProjects.at(i).Configuration.linker.LinkIncremental == linkIncrementalYes ? _True : _False);
+ xml << tag("LinkIncremental")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name))
+ << valueTagT(ts);
+ }
+
+ if ( tool.SingleProjects.at(i).Configuration.preBuild.ExcludedFromBuild != unset )
+ {
+ xml << tag("PreBuildEventUseInBuild")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name))
+ << valueTagT(!tool.SingleProjects.at(i).Configuration.preBuild.ExcludedFromBuild);
+ }
+
+ if ( tool.SingleProjects.at(i).Configuration.preLink.ExcludedFromBuild != unset )
+ {
+ xml << tag("PreLinkEventUseInBuild")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name))
+ << valueTagT(!tool.SingleProjects.at(i).Configuration.preLink.ExcludedFromBuild);
+ }
+
+ if ( tool.SingleProjects.at(i).Configuration.postBuild.ExcludedFromBuild != unset )
+ {
+ xml << tag("PostBuildEventUseInBuild")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name))
+ << valueTagT(!tool.SingleProjects.at(i).Configuration.postBuild.ExcludedFromBuild);
+ }
+ }
+ xml << closetag();
+
+ for (int i = 0; i < tool.SingleProjects.count(); ++i) {
+ xml << tag("ItemDefinitionGroup")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name));
+
+ // ClCompile
+ write(xml, tool.SingleProjects.at(i).Configuration.compiler);
+
+ // Link
+ write(xml, tool.SingleProjects.at(i).Configuration.linker);
+
+ // Midl
+ write(xml, tool.SingleProjects.at(i).Configuration.idl);
+
+ // ResourceCompiler
+ write(xml, tool.SingleProjects.at(i).Configuration.resource);
+
+ // Post build event
+ if ( tool.SingleProjects.at(i).Configuration.postBuild.ExcludedFromBuild != unset )
+ write(xml, tool.SingleProjects.at(i).Configuration.postBuild);
+
+ // Pre build event
+ if ( tool.SingleProjects.at(i).Configuration.preBuild.ExcludedFromBuild != unset )
+ write(xml, tool.SingleProjects.at(i).Configuration.preBuild);
+
+ // Pre link event
+ if ( tool.SingleProjects.at(i).Configuration.preLink.ExcludedFromBuild != unset )
+ write(xml, tool.SingleProjects.at(i).Configuration.preLink);
+
+ xml << closetag();
+ }
+
+ // The file filters are added in a separate file for MSBUILD.
+ QFile filterFile;
+ filterFile.setFileName(Option::output.fileName().append(".filters"));
+ filterFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate);
+ QTextStream ts(&filterFile);
+ XmlOutput xmlFilter(ts, XmlOutput::NoConversion);
+
+ xmlFilter.setIndentString(" ");
+
+ xmlFilter << decl("1.0", "utf-8")
+ << tag("Project")
+ << attrTag("ToolsVersion", "4.0")
+ << attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
+
+ xmlFilter << tag("ItemGroup");
+
+ addFilters(tool, xmlFilter, "Form Files");
+ addFilters(tool, xmlFilter, "Generated Files");
+ addFilters(tool, xmlFilter, "Header Files");
+ addFilters(tool, xmlFilter, "LexYacc Files");
+ addFilters(tool, xmlFilter, "Resource Files");
+ addFilters(tool, xmlFilter, "Source Files");
+ addFilters(tool, xmlFilter, "Translation Files");
+ xmlFilter << closetag();
+
+ outputFilter(tool, xml, xmlFilter, "Source Files");
+ outputFilter(tool, xml, xmlFilter, "Header Files");
+ outputFilter(tool, xml, xmlFilter, "Generated Files");
+ outputFilter(tool, xml, xmlFilter, "LexYacc Files");
+ outputFilter(tool, xml, xmlFilter, "Translation Files");
+ outputFilter(tool, xml, xmlFilter, "Form Files");
+ outputFilter(tool, xml, xmlFilter, "Resource Files");
+ for (int x = 0; x < tool.ExtraCompilers.count(); ++x) {
+ outputFilter(tool, xml, xmlFilter, tool.ExtraCompilers.at(x));
+ }
+ outputFilter(tool, xml, xmlFilter, "Root Files");
+
+ xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets");
+
+ xml << tag("ImportGroup")
+ << attrTag("Label", "ExtensionTargets")
+ << closetag();
+}
+
+static inline QString toString(asmListingOption option)
+{
+ switch (option) {
+ case asmListingAsmMachine:
+ return "AssemblyAndMachineCode";
+ case asmListingAsmMachineSrc:
+ return "All";
+ case asmListingAsmSrc:
+ return "AssemblyAndSourceCode";
+ case asmListingAssemblyOnly:
+ return "AssemblyCode";
+ }
+ return QString();
+}
+
+static inline QString toString(basicRuntimeCheckOption option)
+{
+ switch (option) {
+ case runtimeBasicCheckNone:
+ return "";
+ case runtimeCheckStackFrame:
+ return "StackFrameRuntimeCheck";
+ case runtimeCheckUninitVariables:
+ return "UninitializedLocalUsageCheck";
+ case runtimeBasicCheckAll:
+ return "EnableFastChecks";
+ }
+ return QString();
+}
+
+static inline QString toString(callingConventionOption option)
+{
+ switch (option) {
+ case callConventionCDecl:
+ return "Cdecl";
+ case callConventionFastCall:
+ return "FastCall";
+ case callConventionStdCall:
+ return "StdCall";
+ }
+ return QString();
+}
+
+static inline QString toString(CompileAsOptions option)
+{
+ switch (option) {
+ case compileAsC:
+ return "CompileAsC";
+ case compileAsCPlusPlus:
+ return "CompileAsCpp";
+ }
+ return QString();
+}
+
+static inline QString toString(compileAsManagedOptions option)
+{
+ switch (option) {
+ case managedAssembly:
+ return "true";
+ case managedAssemblyPure:
+ return "Safe";
+ case managedAssemblyOldSyntax:
+ return "OldSyntax";
+ }
+ return QString();
+}
+
+static inline QString toString(debugOption option)
+{
+ switch (option) {
+ case debugOldStyleInfo:
+ return "OldStyle";
+ case debugEditAndContinue:
+ return "EditAndContinue";
+ case debugEnabled:
+ return "ProgramDatabase";
+ }
+ return QString();
+}
+
+static inline QString toString(enhancedInstructionSetOption option)
+{
+ switch (option) {
+ case archSSE:
+ return "StreamingSIMDExtensions";
+ case archSSE2:
+ return "StreamingSIMDExtensions2";
+ }
+ return QString();
+}
+
+static inline QString toString(exceptionHandling option)
+{
+ switch (option) {
+ case ehNone:
+ return "false";
+ case ehNoSEH:
+ return "Sync";
+ case ehSEH:
+ return "Async";
+ }
+ return QString();
+}
+
+static inline QString toString(favorSizeOrSpeedOption option)
+{
+ switch (option) {
+ case favorSize:
+ return "Size";
+ case favorSpeed:
+ return "Speed";
+ }
+ return QString();
+}
+
+static inline QString toString(floatingPointModel option)
+{
+ switch (option) {
+ case floatingPointFast:
+ return "Fast";
+ case floatingPointPrecise:
+ return "Precise";
+ case floatingPointStrict:
+ return "Strict";
+ }
+ return QString();
+}
+
+static inline QString toString(inlineExpansionOption option)
+{
+ switch (option) {
+ case expandDisable:
+ return "Disabled";
+ case expandOnlyInline:
+ return "OnlyExplicitInline";
+ case expandAnySuitable:
+ return "AnySuitable";
+ }
+ return QString();
+}
+
+static inline QString toString(optimizeOption option)
+{
+ switch (option) {
+ case optimizeMinSpace:
+ return "MinSpace";
+ case optimizeMaxSpeed:
+ return "MaxSpeed";
+ }
+ return QString();
+}
+
+static inline QString toString(pchOption option)
+{
+ switch (option) {
+ case pchNone:
+ return "NotUsing";
+ case pchCreateUsingSpecific:
+ return "Create";
+ case pchUseUsingSpecific:
+ return "Use";
+ }
+ return QString();
+}
+
+static inline QString toString(runtimeLibraryOption option)
+{
+ switch (option) {
+ case rtMultiThreaded:
+ return "MultiThreaded";
+ case rtMultiThreadedDLL:
+ return "MultiThreadedDLL";
+ case rtMultiThreadedDebug:
+ return "MultiThreadedDebug";
+ case rtMultiThreadedDebugDLL:
+ return "MultiThreadedDebugDLL";
+ }
+ return QString();
+}
+
+static inline QString toString(structMemberAlignOption option)
+{
+ switch (option) {
+ case alignSingleByte:
+ return "1Byte";
+ case alignTwoBytes:
+ return "2Bytes";
+ case alignFourBytes:
+ return "4Bytes";
+ case alignEightBytes:
+ return "8Bytes";
+ case alignSixteenBytes:
+ return "16Bytes";
+ }
+ return QString();
+}
+
+static inline QString toString(warningLevelOption option)
+{
+ switch (option) {
+ case warningLevel_0:
+ return "TurnOffAllWarnings";
+ case warningLevel_1:
+ return "Level1";
+ case warningLevel_2:
+ return "Level2";
+ case warningLevel_3:
+ return "Level3";
+ case warningLevel_4:
+ return "Level4";
+ }
+ return QString();
+}
+
+static inline QString toString(optLinkTimeCodeGenType option)
+{
+ switch (option) {
+ case optLTCGEnabled:
+ return "UseLinkTimeCodeGeneration";
+ case optLTCGInstrument:
+ return "PGInstrument";
+ case optLTCGOptimize:
+ return "PGOptimization";
+ case optLTCGUpdate:
+ return "PGUpdate";
+ }
+ return QString();
+}
+
+static inline QString toString(subSystemOption option)
+{
+ switch (option) {
+ case subSystemConsole:
+ return "Console";
+ case subSystemWindows:
+ return "Windows";
+ }
+ return QString();
+}
+
+static inline QString toString(machineTypeOption option)
+{
+ switch (option) {
+ case machineX86:
+ return "MachineX86";
+ case machineX64:
+ return "MachineX64";
+ }
+ return QString();
+}
+
+static inline QString toString(midlCharOption option)
+{
+ switch (option) {
+ case midlCharUnsigned:
+ return "Unsigned";
+ case midlCharSigned:
+ return "Signed";
+ case midlCharAscii7:
+ return "Ascii";
+ }
+ return QString();
+}
+
+static inline QString toString(midlErrorCheckOption option)
+{
+ switch (option) {
+ case midlDisableAll:
+ return "None";
+ case midlEnableAll:
+ return "All";
+ }
+ return QString();
+}
+
+static inline QString toString(midlStructMemberAlignOption option)
+{
+ switch (option) {
+ case midlAlignSingleByte:
+ return "1";
+ case midlAlignTwoBytes:
+ return "2";
+ case midlAlignFourBytes:
+ return "4";
+ case midlAlignEightBytes:
+ return "8";
+ case midlAlignSixteenBytes:
+ return "16";
+ }
+ return QString();
+}
+
+static inline QString toString(midlTargetEnvironment option)
+{
+ switch (option) {
+ case midlTargetWin32:
+ return "Win32";
+ case midlTargetWin64:
+ return "X64";
+ }
+ return QString();
+}
+
+static inline QString toString(midlWarningLevelOption option)
+{
+ switch (option) {
+ case midlWarningLevel_0:
+ return "0";
+ case midlWarningLevel_1:
+ return "1";
+ case midlWarningLevel_2:
+ return "2";
+ case midlWarningLevel_3:
+ return "3";
+ case midlWarningLevel_4:
+ return "4";
+ }
+ return QString();
+}
+
+static inline QString toString(enumResourceLangID option)
+{
+ if (option == 0)
+ return QString();
+ else
+ return QString::number(qlonglong(option));
+}
+
+static inline QString toString(charSet option)
+{
+ switch (option) {
+ case charSetNotSet:
+ return "NotSet";
+ case charSetUnicode:
+ return "Unicode";
+ case charSetMBCS:
+ return "MultiByte";
+ }
+ return QString();
+}
+
+static inline QString toString(ConfigurationTypes option)
+{
+ switch (option) {
+ case typeApplication:
+ return "Application";
+ case typeDynamicLibrary:
+ return "DynamicLibrary";
+ case typeStaticLibrary:
+ return "StaticLibrary";
+ }
+ return QString();
+}
+
+static inline QString toString(useOfATL option)
+{
+ switch (option) {
+ case useATLStatic:
+ return "Static";
+ case useATLDynamic:
+ return "Dynamic";
+ }
+ return QString();
+}
+
+static inline QString toString(useOfMfc option)
+{
+ switch (option) {
+ case useMfcStatic:
+ return "Static";
+ case useMfcDynamic:
+ return "Dynamic";
+ }
+ return QString();
+}
+
+static inline triState toTriState(browseInfoOption option)
+{
+ switch (option)
+ {
+ case brInfoNone:
+ return _False;
+ case brAllInfo:
+ case brNoLocalSymbols:
+ return _True;
+ }
+ return unset;
+}
+
+static inline triState toTriState(preprocessOption option)
+{
+ switch (option)
+ {
+ case preprocessNo:
+ return _False;
+ case preprocessNoLineNumbers:
+ case preprocessYes:
+ return _True;
+ }
+ return unset;
+}
+
+static inline triState toTriState(optFoldingType option)
+{
+ switch (option)
+ {
+ case optNoFolding:
+ return _False;
+ case optFolding:
+ return _True;
+ }
+ return unset;
+}
+
+static inline triState toTriState(addressAwarenessType option)
+{
+ switch (option)
+ {
+ case addrAwareDefault:
+ return unset;
+ case addrAwareNoLarge:
+ return _False;
+ case addrAwareLarge:
+ return _True;
+ }
+ return unset;
+}
+
+static inline triState toTriState(linkIncrementalType option)
+{
+ switch (option)
+ {
+ case linkIncrementalDefault:
+ return unset;
+ case linkIncrementalNo:
+ return _False;
+ case linkIncrementalYes:
+ return _True;
+ }
+ return unset;
+}
+
+static inline triState toTriState(linkProgressOption option)
+{
+ switch (option)
+ {
+ case linkProgressNotSet:
+ return unset;
+ case linkProgressAll:
+ case linkProgressLibs:
+ return _True;
+ }
+ return unset;
+}
+
+static inline triState toTriState(optRefType option)
+{
+ switch (option)
+ {
+ case optReferencesDefault:
+ return unset;
+ case optNoReferences:
+ return _False;
+ case optReferences:
+ return _True;
+ }
+ return unset;
+}
+
+static inline triState toTriState(termSvrAwarenessType option)
+{
+ switch (option)
+ {
+ case termSvrAwareDefault:
+ return unset;
+ case termSvrAwareNo:
+ return _False;
+ case termSvrAwareYes:
+ return _True;
+ }
+ return unset;
+}
+
+void VCXProjectWriter::write(XmlOutput &xml, const VCCLCompilerTool &tool)
+{
+ xml
+ << tag(_CLCompile)
+ << attrTagX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories, ";")
+ << attrTagX(_AdditionalOptions, tool.AdditionalOptions, " ")
+ << attrTagX(_AdditionalUsingDirectories, tool.AdditionalUsingDirectories, ";")
+//unused << attrTagS(_AlwaysAppend, tool.AlwaysAppend)
+ << attrTagS(_AssemblerListingLocation, tool.AssemblerListingLocation)
+ << attrTagS(_AssemblerOutput, toString(tool.AssemblerOutput))
+ << attrTagS(_BasicRuntimeChecks, toString(tool.BasicRuntimeChecks))
+ << attrTagT(_BrowseInformation, toTriState(tool.BrowseInformation))
+ << attrTagS(_BrowseInformationFile, tool.BrowseInformationFile)
+ << attrTagT(_BufferSecurityCheck, tool.BufferSecurityCheck)
+ << attrTagS(_CallingConvention, toString(tool.CallingConvention))
+ << attrTagS(_CompileAs, toString(tool.CompileAs))
+ << attrTagS(_CompileAsManaged, toString(tool.CompileAsManaged))
+ << attrTagT(_CreateHotpatchableImage, tool.CreateHotpatchableImage)
+ << attrTagS(_DebugInformationFormat, toString(tool.DebugInformationFormat))
+ << attrTagT(_DisableLanguageExtensions, tool.DisableLanguageExtensions)
+ << attrTagX(_DisableSpecificWarnings, tool.DisableSpecificWarnings, ";")
+ << attrTagS(_EnableEnhancedInstructionSet, toString(tool.EnableEnhancedInstructionSet))
+ << attrTagT(_EnableFiberSafeOptimizations, tool.EnableFiberSafeOptimizations)
+ << attrTagT(_EnablePREfast, tool.EnablePREfast)
+ << attrTagS(_ErrorReporting, tool.ErrorReporting)
+ << attrTagS(_ExceptionHandling, toString(tool.ExceptionHandling))
+ << attrTagT(_ExpandAttributedSource, tool.ExpandAttributedSource)
+ << attrTagS(_FavorSizeOrSpeed, toString(tool.FavorSizeOrSpeed))
+ << attrTagT(_FloatingPointExceptions, tool.FloatingPointExceptions)
+ << attrTagS(_FloatingPointModel, toString(tool.FloatingPointModel))
+ << attrTagT(_ForceConformanceInForLoopScope, tool.ForceConformanceInForLoopScope)
+ << attrTagX(_ForcedIncludeFiles, tool.ForcedIncludeFiles, ";")
+ << attrTagX(_ForcedUsingFiles, tool.ForcedUsingFiles, ";")
+ << attrTagT(_FunctionLevelLinking, tool.EnableFunctionLevelLinking)
+ << attrTagT(_GenerateXMLDocumentationFiles, tool.GenerateXMLDocumentationFiles)
+ << attrTagT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath)
+ << attrTagS(_InlineFunctionExpansion, toString(tool.InlineFunctionExpansion))
+ << attrTagT(_IntrinsicFunctions, tool.EnableIntrinsicFunctions)
+ << attrTagT(_MinimalRebuild, tool.MinimalRebuild)
+ << attrTagT(_MultiProcessorCompilation, tool.MultiProcessorCompilation)
+ << attrTagS(_ObjectFileName, tool.ObjectFile)
+//unused << attrTagX(_ObjectFiles, tool.ObjectFiles, ";")
+ << attrTagT(_OmitDefaultLibName, tool.OmitDefaultLibName)
+ << attrTagT(_OmitFramePointers, tool.OmitFramePointers)
+ << attrTagT(_OpenMPSupport, tool.OpenMP)
+ << attrTagS(_Optimization, toString(tool.Optimization))
+ << attrTagS(_PrecompiledHeader, toString(tool.UsePrecompiledHeader))
+ << attrTagS(_PrecompiledHeaderFile, tool.PrecompiledHeaderThrough)
+ << attrTagS(_PrecompiledHeaderOutputFile, tool.PrecompiledHeaderFile)
+ << attrTagT(_PreprocessKeepComments, tool.KeepComments)
+ << attrTagX(_PreprocessorDefinitions, tool.PreprocessorDefinitions, ";")
+ << attrTagS(_PreprocessOutputPath, tool.PreprocessOutputPath)
+ << attrTagT(_PreprocessSuppressLineNumbers, tool.PreprocessSuppressLineNumbers)
+ << attrTagT(_PreprocessToFile, toTriState(tool.GeneratePreprocessedFile))
+ << attrTagS(_ProgramDataBaseFileName, tool.ProgramDataBaseFileName)
+ << attrTagS(_ProcessorNumber, tool.MultiProcessorCompilationProcessorCount)
+ << attrTagS(_RuntimeLibrary, toString(tool.RuntimeLibrary))
+ << attrTagT(_RuntimeTypeInfo, tool.RuntimeTypeInfo)
+ << attrTagT(_ShowIncludes, tool.ShowIncludes)
+ << attrTagT(_SmallerTypeCheck, tool.SmallerTypeCheck)
+ << attrTagT(_StringPooling, tool.StringPooling)
+ << attrTagS(_StructMemberAlignment, toString(tool.StructMemberAlignment))
+ << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner)
+//unused << attrTagS(_TreatSpecificWarningsAsErrors, tool.TreatSpecificWarningsAsErrors)
+ << attrTagT(_TreatWarningAsError, tool.WarnAsError)
+ << attrTagT(_TreatWChar_tAsBuiltInType, tool.TreatWChar_tAsBuiltInType)
+ << attrTagT(_UndefineAllPreprocessorDefinitions, tool.UndefineAllPreprocessorDefinitions)
+ << attrTagX(_UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions, ";")
+ << attrTagT(_UseFullPaths, tool.DisplayFullPaths)
+ << attrTagT(_UseUnicodeForAssemblerListing, tool.UseUnicodeForAssemblerListing)
+ << attrTagS(_WarningLevel, toString(tool.WarningLevel))
+ << attrTagT(_WholeProgramOptimization, tool.WholeProgramOptimization)
+ << attrTagS(_XMLDocumentationFileName, tool.XMLDocumentationFileName)
+ << closetag(_CLCompile);
+}
+
+void VCXProjectWriter::write(XmlOutput &xml, const VCLinkerTool &tool)
+{
+ xml
+ << tag(_Link)
+ << attrTagX(_AdditionalDependencies, tool.AdditionalDependencies, ";")
+ << attrTagX(_AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories, ";")
+ << attrTagX(_AdditionalManifestDependencies, tool.AdditionalManifestDependencies, ";")
+ << attrTagX(_AdditionalOptions, tool.AdditionalOptions, " ")
+ << attrTagX(_AddModuleNamesToAssembly, tool.AddModuleNamesToAssembly, ";")
+ << attrTagT(_AllowIsolation, tool.AllowIsolation)
+ << attrTagT(_AssemblyDebug, tool.AssemblyDebug)
+ << attrTagX(_AssemblyLinkResource, tool.AssemblyLinkResource, ";")
+ << attrTagS(_BaseAddress, tool.BaseAddress)
+ << attrTagS(_CLRImageType, tool.CLRImageType)
+ << attrTagS(_CLRSupportLastError, tool.CLRSupportLastError)
+ << attrTagS(_CLRThreadAttribute, tool.CLRThreadAttribute)
+ << attrTagT(_CLRUnmanagedCodeCheck, tool.CLRUnmanagedCodeCheck)
+//unused << attrTagS(_CreateHotPatchableImage, tool.CreateHotPatchableImage)
+ << attrTagT(_DataExecutionPrevention, tool.DataExecutionPrevention)
+ << attrTagX(_DelayLoadDLLs, tool.DelayLoadDLLs, ";")
+ << attrTagT(_DelaySign, tool.DelaySign)
+ << attrTagS(_EmbedManagedResourceFile, tool.LinkToManagedResourceFile)
+ << attrTagT(_EnableCOMDATFolding, toTriState(tool.EnableCOMDATFolding))
+ << attrTagT(_EnableUAC, tool.EnableUAC)
+ << attrTagS(_EntryPointSymbol, tool.EntryPointSymbol)
+ << attrTagX(_ForceSymbolReferences, tool.ForceSymbolReferences, ";")
+ << attrTagS(_FunctionOrder, tool.FunctionOrder)
+ << attrTagT(_GenerateDebugInformation, tool.GenerateDebugInformation)
+ << attrTagT(_GenerateManifest, tool.GenerateManifest)
+ << attrTagT(_GenerateMapFile, tool.GenerateMapFile)
+ << attrTagL(_HeapCommitSize, tool.HeapCommitSize, /*ifNot*/ -1)
+ << attrTagL(_HeapReserveSize, tool.HeapReserveSize, /*ifNot*/ -1)
+ << attrTagT(_IgnoreAllDefaultLibraries, tool.IgnoreAllDefaultLibraries)
+ << attrTagT(_IgnoreEmbeddedIDL, tool.IgnoreEmbeddedIDL)
+ << attrTagT(_IgnoreImportLibrary, tool.IgnoreImportLibrary)
+ << attrTagX(_IgnoreSpecificDefaultLibraries, tool.IgnoreDefaultLibraryNames, ";")
+ << attrTagS(_ImportLibrary, tool.ImportLibrary)
+ << attrTagS(_KeyContainer, tool.KeyContainer)
+ << attrTagS(_KeyFile, tool.KeyFile)
+ << attrTagT(_LargeAddressAware, toTriState(tool.LargeAddressAware))
+ << attrTagT(_LinkDLL, (tool.config->ConfigurationType == typeDynamicLibrary ? _True : unset))
+ << attrTagS(_LinkErrorReporting, tool.LinkErrorReporting)
+ << attrTagT(_LinkIncremental, toTriState(tool.LinkIncremental))
+ << attrTagT(_LinkStatus, toTriState(tool.ShowProgress))
+ << attrTagS(_LinkTimeCodeGeneration, toString(tool.LinkTimeCodeGeneration))
+ << attrTagS(_ManifestFile, tool.ManifestFile)
+ << attrTagT(_MapExports, tool.MapExports)
+ << attrTagS(_MapFileName, tool.MapFileName)
+ << attrTagS(_MergedIDLBaseFileName, tool.MergedIDLBaseFileName)
+ << attrTagS(_MergeSections, tool.MergeSections)
+ << attrTagS(_MidlCommandFile, tool.MidlCommandFile)
+ << attrTagS(_ModuleDefinitionFile, tool.ModuleDefinitionFile)
+ << attrTagT(_NoEntryPoint, tool.ResourceOnlyDLL)
+ << attrTagT(_OptimizeReferences, toTriState(tool.OptimizeReferences))
+ << attrTagS(_OutputFile, tool.OutputFile)
+ << attrTagT(_PreventDllBinding, tool.PreventDllBinding)
+ << attrTagS(_ProgramDatabaseFile, tool.ProgramDatabaseFile)
+ << attrTagT(_RandomizedBaseAddress, tool.RandomizedBaseAddress)
+ << attrTagT(_RegisterOutput, tool.RegisterOutput)
+ << attrTagL(_SectionAlignment, tool.SectionAlignment, /*ifNot*/ -1)
+ << attrTagT(_SetChecksum, tool.SetChecksum)
+ << attrTagL(_StackCommitSize, tool.StackCommitSize, /*ifNot*/ -1)
+ << attrTagL(_StackReserveSize, tool.StackReserveSize, /*ifNot*/ -1)
+ << attrTagS(_StripPrivateSymbols, tool.StripPrivateSymbols)
+ << attrTagS(_SubSystem, toString(tool.SubSystem))
+// << attrTagT(_SupportNobindOfDelayLoadedDLL, tool.SupportNobindOfDelayLoadedDLL)
+ << attrTagT(_SupportUnloadOfDelayLoadedDLL, tool.SupportUnloadOfDelayLoadedDLL)
+ << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner)
+ << attrTagT(_SwapRunFromCD, tool.SwapRunFromCD)
+ << attrTagT(_SwapRunFromNet, tool.SwapRunFromNet)
+ << attrTagS(_TargetMachine, toString(tool.TargetMachine))
+ << attrTagT(_TerminalServerAware, toTriState(tool.TerminalServerAware))
+ << attrTagT(_TreatLinkerWarningAsErrors, tool.TreatWarningsAsErrors)
+ << attrTagT(_TurnOffAssemblyGeneration, tool.TurnOffAssemblyGeneration)
+ << attrTagS(_TypeLibraryFile, tool.TypeLibraryFile)
+ << attrTagL(_TypeLibraryResourceID, tool.TypeLibraryResourceID, /*ifNot*/ 0)
+ << attrTagS(_UACExecutionLevel, tool.UACExecutionLevel)
+ << attrTagT(_UACUIAccess, tool.UACUIAccess)
+ << attrTagS(_Version, tool.Version)
+ << closetag(_Link);
+}
+
+void VCXProjectWriter::write(XmlOutput &xml, const VCMIDLTool &tool)
+{
+ xml
+ << tag(_Midl)
+ << attrTagX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories, ";")
+ << attrTagX(_AdditionalOptions, tool.AdditionalOptions, " ")
+ << attrTagT(_ApplicationConfigurationMode, tool.ApplicationConfigurationMode)
+ << attrTagS(_ClientStubFile, tool.ClientStubFile)
+ << attrTagX(_CPreprocessOptions, tool.CPreprocessOptions, " ")
+ << attrTagS(_DefaultCharType, toString(tool.DefaultCharType))
+ << attrTagS(_DLLDataFileName, tool.DLLDataFileName)
+ << attrTagS(_EnableErrorChecks, toString(tool.EnableErrorChecks))
+ << attrTagT(_ErrorCheckAllocations, tool.ErrorCheckAllocations)
+ << attrTagT(_ErrorCheckBounds, tool.ErrorCheckBounds)
+ << attrTagT(_ErrorCheckEnumRange, tool.ErrorCheckEnumRange)
+ << attrTagT(_ErrorCheckRefPointers, tool.ErrorCheckRefPointers)
+ << attrTagT(_ErrorCheckStubData, tool.ErrorCheckStubData)
+ << attrTagS(_GenerateClientFiles, tool.GenerateClientFiles)
+ << attrTagS(_GenerateServerFiles, tool.GenerateServerFiles)
+ << attrTagT(_GenerateStublessProxies, tool.GenerateStublessProxies)
+ << attrTagT(_GenerateTypeLibrary, tool.GenerateTypeLibrary)
+ << attrTagS(_HeaderFileName, tool.HeaderFileName)
+ << attrTagT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath)
+ << attrTagS(_InterfaceIdentifierFileName, tool.InterfaceIdentifierFileName)
+ << attrTagL(_LocaleID, tool.LocaleID, /*ifNot*/ -1)
+ << attrTagT(_MkTypLibCompatible, tool.MkTypLibCompatible)
+ << attrTagS(_OutputDirectory, tool.OutputDirectory)
+ << attrTagX(_PreprocessorDefinitions, tool.PreprocessorDefinitions, ";")
+ << attrTagS(_ProxyFileName, tool.ProxyFileName)
+ << attrTagS(_RedirectOutputAndErrors, tool.RedirectOutputAndErrors)
+ << attrTagS(_ServerStubFile, tool.ServerStubFile)
+ << attrTagS(_StructMemberAlignment, toString(tool.StructMemberAlignment))
+ << attrTagT(_SuppressCompilerWarnings, tool.SuppressCompilerWarnings)
+ << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner)
+ << attrTagS(_TargetEnvironment, toString(tool.TargetEnvironment))
+ << attrTagS(_TypeLibFormat, tool.TypeLibFormat)
+ << attrTagS(_TypeLibraryName, tool.TypeLibraryName)
+ << attrTagX(_UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions, ";")
+ << attrTagT(_ValidateAllParameters, tool.ValidateAllParameters)
+ << attrTagT(_WarnAsError, tool.WarnAsError)
+ << attrTagS(_WarningLevel, toString(tool.WarningLevel))
+ << closetag(_Midl);
+}
+
+void VCXProjectWriter::write(XmlOutput &xml, const VCCustomBuildTool &tool)
+{
+ const QString &configName = tool.config->Name;
+
+ if ( !tool.AdditionalDependencies.isEmpty() )
+ {
+ xml << tag("AdditionalInputs")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(configName))
+ << valueTagDefX(tool.AdditionalDependencies, "AdditionalInputs", ";");
+ }
+
+ if( !tool.CommandLine.isEmpty() )
+ {
+ xml << tag("Command")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(configName))
+ << valueTag(tool.CommandLine.join(vcxCommandSeparator()));
+ }
+
+ if ( !tool.Description.isEmpty() )
+ {
+ xml << tag("Message")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(configName))
+ << valueTag(tool.Description);
+ }
+
+ if ( !tool.Outputs.isEmpty() )
+ {
+ xml << tag("Outputs")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(configName))
+ << valueTagDefX(tool.Outputs, "Outputs", ";");
+ }
+}
+
+void VCXProjectWriter::write(XmlOutput &xml, const VCLibrarianTool &tool)
+{
+ xml
+ << tag(_Link)
+ << attrTagX(_AdditionalDependencies, tool.AdditionalDependencies, ";")
+ << attrTagX(_AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories, ";")
+ << attrTagX(_AdditionalOptions, tool.AdditionalOptions, " ")
+//unused << attrTagS(_DisplayLibrary, tool.DisplayLibrary)
+//unused << attrTagS(_ErrorReporting, tool.ErrorReporting)
+ << attrTagX(_ExportNamedFunctions, tool.ExportNamedFunctions, ";")
+ << attrTagX(_ForceSymbolReferences, tool.ForceSymbolReferences, ";")
+ << attrTagT(_IgnoreAllDefaultLibraries, tool.IgnoreAllDefaultLibraries)
+ << attrTagX(_IgnoreSpecificDefaultLibraries, tool.IgnoreDefaultLibraryNames, ";")
+//unused << attrTagT(_LinkTimeCodeGeneration, tool.LinkTimeCodeGeneration)
+ << attrTagS(_ModuleDefinitionFile, tool.ModuleDefinitionFile)
+//unused << attrTagS(_Name, tool.Name)
+ << attrTagS(_OutputFile, tool.OutputFile)
+//unused << attrTagX(_RemoveObjects, tool.RemoveObjects, ";")
+//unused << attrTagS(_SubSystem, tool.SubSystem)
+ << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner)
+//unused << attrTagS(_TargetMachine, tool.TargetMachine)
+//unused << attrTagT(_TreatLibWarningAsErrors, tool.TreatLibWarningAsErrors)
+//unused << attrTagT(_Verbose, tool.Verbose)
+ << closetag(_Link);
+}
+
+void VCXProjectWriter::write(XmlOutput &xml, const VCResourceCompilerTool &tool)
+{
+ xml
+ << tag(_ResourceCompile)
+ << attrTagX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories, ";")
+ << attrTagX(_AdditionalOptions, tool.AdditionalOptions, " ")
+ << attrTagS(_Culture, toString(tool.Culture))
+ << attrTagT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath)
+//unused << attrTagT(_NullTerminateStrings, tool.NullTerminateStrings)
+ << attrTagX(_PreprocessorDefinitions, tool.PreprocessorDefinitions, ";")
+ << attrTagS(_ResourceOutputFileName, tool.ResourceOutputFileName)
+ << attrTagT(_ShowProgress, toTriState(tool.ShowProgress))
+ << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner)
+//unused << attrTagS(_TrackerLogDirectory, tool.TrackerLogDirectory)
+//unused << attrTagS(_UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions)
+ << closetag(_ResourceCompile);
+}
+
+void VCXProjectWriter::write(XmlOutput &xml, const VCEventTool &tool)
+{
+ xml
+ << tag(tool.EventName)
+ << attrTagS(_Command, tool.CommandLine.join(vcxCommandSeparator()))
+ << attrTagS(_Message, tool.Description)
+ << closetag(tool.EventName);
+}
+
+void VCXProjectWriter::write(XmlOutput &xml, const VCDeploymentTool &tool)
+{
+ Q_UNUSED(xml);
+ Q_UNUSED(tool);
+ // SmartDevice deployment not supported in VS 2010
+}
+
+void VCXProjectWriter::write(XmlOutput &xml, const VCConfiguration &tool)
+{
+ xml << tag("PropertyGroup")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Name))
+ << attrTag("Label", "Configuration")
+ << attrTagS(_OutputDirectory, tool.OutputDirectory)
+ << attrTagT(_ATLMinimizesCRunTimeLibraryUsage, tool.ATLMinimizesCRunTimeLibraryUsage)
+ << attrTagT(_BuildBrowserInformation, tool.BuildBrowserInformation)
+ << attrTagS(_CharacterSet, toString(tool.CharacterSet))
+ << attrTagS(_ConfigurationType, toString(tool.ConfigurationType))
+ << attrTagS(_DeleteExtensionsOnClean, tool.DeleteExtensionsOnClean)
+ << attrTagS(_ImportLibrary, tool.ImportLibrary)
+ << attrTagS(_IntermediateDirectory, tool.IntermediateDirectory)
+ << attrTagS(_PrimaryOutput, tool.PrimaryOutput)
+ << attrTagS(_ProgramDatabase, tool.ProgramDatabase)
+ << attrTagT(_RegisterOutput, tool.RegisterOutput)
+ << attrTagS(_UseOfATL, toString(tool.UseOfATL))
+ << attrTagS(_UseOfMfc, toString(tool.UseOfMfc))
+ << attrTagT(_WholeProgramOptimization, tool.WholeProgramOptimization)
+ << closetag();
+}
+
+void VCXProjectWriter::write(XmlOutput &xml, VCFilter &tool)
+{
+ Q_UNUSED(xml);
+ Q_UNUSED(tool);
+ // unused in this generator
+}
+
+void VCXProjectWriter::addFilters(VCProject &project, XmlOutput &xmlFilter, const QString &filtername)
+{
+ bool added = false;
+
+ for (int i = 0; i < project.SingleProjects.count(); ++i) {
+ VCFilter filter;
+ const VCProjectSingleConfig &singleCfg = project.SingleProjects.at(i);
+ if (filtername == "Root Files") {
+ filter = singleCfg.RootFiles;
+ } else if (filtername == "Source Files") {
+ filter = singleCfg.SourceFiles;
+ } else if (filtername == "Header Files") {
+ filter = singleCfg.HeaderFiles;
+ } else if (filtername == "Generated Files") {
+ filter = singleCfg.GeneratedFiles;
+ } else if (filtername == "LexYacc Files") {
+ filter = singleCfg.LexYaccFiles;
+ } else if (filtername == "Translation Files") {
+ filter = singleCfg.TranslationFiles;
+ } else if (filtername == "Form Files") {
+ filter = singleCfg.FormFiles;
+ } else if (filtername == "Resource Files") {
+ filter = singleCfg.ResourceFiles;
+ } else {
+ // ExtraCompilers
+ filter = project.SingleProjects[i].filterForExtraCompiler(filtername);
+ }
+
+ if(!filter.Files.isEmpty() && !added) {
+ xmlFilter << tag("Filter")
+ << attrTag("Include", filtername)
+ << attrTagS("UniqueIdentifier", filter.Guid)
+ << attrTagS("Extensions", filter.Filter)
+ << attrTagT("ParseFiles", filter.ParseFiles)
+ << closetag();
+ }
+ }
+}
+
+// outputs a given filter for all existing configurations of a project
+void VCXProjectWriter::outputFilter(VCProject &project, XmlOutput &xml, XmlOutput &xmlFilter, const QString &filtername)
+{
+ XNode *root;
+ if (project.SingleProjects.at(0).flat_files)
+ root = new XFlatNode;
+ else
+ root = new XTreeNode;
+
+ QString name, extfilter;
+ triState parse;
+
+ for (int i = 0; i < project.SingleProjects.count(); ++i) {
+ VCFilter filter;
+ const VCProjectSingleConfig &singleCfg = project.SingleProjects.at(i);
+ if (filtername == "Root Files") {
+ filter = singleCfg.RootFiles;
+ } else if (filtername == "Source Files") {
+ filter = singleCfg.SourceFiles;
+ } else if (filtername == "Header Files") {
+ filter = singleCfg.HeaderFiles;
+ } else if (filtername == "Generated Files") {
+ filter = singleCfg.GeneratedFiles;
+ } else if (filtername == "LexYacc Files") {
+ filter = singleCfg.LexYaccFiles;
+ } else if (filtername == "Translation Files") {
+ filter = singleCfg.TranslationFiles;
+ } else if (filtername == "Form Files") {
+ filter = singleCfg.FormFiles;
+ } else if (filtername == "Resource Files") {
+ filter = singleCfg.ResourceFiles;
+ } else {
+ // ExtraCompilers
+ filter = project.SingleProjects[i].filterForExtraCompiler(filtername);
+ }
+
+ // Merge all files in this filter to root tree
+ for (int x = 0; x < filter.Files.count(); ++x)
+ root->addElement(filter.Files.at(x));
+
+ // Save filter setting from first filter. Next filters
+ // may differ but we cannot handle that. (ex. extfilter)
+ if (name.isEmpty()) {
+ name = filter.Name;
+ extfilter = filter.Filter;
+ parse = filter.ParseFiles;
+ }
+ }
+
+ if (!root->hasElements())
+ return;
+
+ root->generateXML(xml, xmlFilter, "", project, filtername); // output root tree
+}
+
+// Output all configurations (by filtername) for a file (by info)
+// A filters config output is in VCFilter.outputFileConfig()
+void VCXProjectWriter::outputFileConfigs(VCProject &project, XmlOutput &xml, XmlOutput &xmlFilter, const VCFilterFile &info, const QString &filtername)
+{
+ // We need to check if the file has any custom build step.
+ // If there is one then it has to be included with "CustomBuild Include"
+ bool fileAdded = false;
+
+ for (int i = 0; i < project.SingleProjects.count(); ++i) {
+ VCFilter filter;
+ const VCProjectSingleConfig &singleCfg = project.SingleProjects.at(i);
+ if (filtername.startsWith("Root Files")) {
+ filter = singleCfg.RootFiles;
+ } else if (filtername.startsWith("Source Files")) {
+ filter = singleCfg.SourceFiles;
+ } else if (filtername.startsWith("Header Files")) {
+ filter = singleCfg.HeaderFiles;
+ } else if (filtername.startsWith("Generated Files")) {
+ filter = singleCfg.GeneratedFiles;
+ } else if (filtername.startsWith("LexYacc Files")) {
+ filter = singleCfg.LexYaccFiles;
+ } else if (filtername.startsWith("Translation Files")) {
+ filter = singleCfg.TranslationFiles;
+ } else if (filtername.startsWith("Form Files")) {
+ filter = singleCfg.FormFiles;
+ } else if (filtername.startsWith("Resource Files")) {
+ filter = singleCfg.ResourceFiles;
+ } else {
+ // ExtraCompilers
+ filter = project.SingleProjects[i].filterForExtraCompiler(filtername);
+ }
+
+ if (filter.Config) // only if the filter is not empty
+ if (outputFileConfig(filter, xml, xmlFilter, info.file, filtername, fileAdded)) // only add it once.
+ fileAdded = true;
+ }
+
+ if ( !fileAdded )
+ {
+ if (filtername.startsWith("Source Files")) {
+
+ xmlFilter << tag("ClCompile")
+ << attrTag("Include",Option::fixPathToLocalOS(info.file))
+ << attrTagS("Filter", filtername);
+
+ xml << tag("ClCompile")
+ << attrTag("Include",Option::fixPathToLocalOS(info.file));
+
+ } else if(filtername.startsWith("Header Files")) {
+
+ xmlFilter << tag("ClInclude")
+ << attrTag("Include",Option::fixPathToLocalOS(info.file))
+ << attrTagS("Filter", filtername);
+
+ xml << tag("ClInclude")
+ << attrTag("Include",Option::fixPathToLocalOS(info.file));
+ } else if(filtername.startsWith("Generated Files") || filtername.startsWith("Form Files")) {
+
+ if (info.file.endsWith(".h")) {
+
+ xmlFilter << tag("ClInclude")
+ << attrTag("Include",Option::fixPathToLocalOS(info.file))
+ << attrTagS("Filter", filtername);
+
+ xml << tag("ClInclude")
+ << attrTag("Include",Option::fixPathToLocalOS(info.file));
+ } else if(info.file.endsWith(".cpp")) {
+
+ xmlFilter << tag("ClCompile")
+ << attrTag("Include",Option::fixPathToLocalOS(info.file))
+ << attrTagS("Filter", filtername);
+
+ xml << tag("ClCompile")
+ << attrTag("Include",Option::fixPathToLocalOS(info.file));
+ } else if(info.file.endsWith(".res")) {
+
+ xmlFilter << tag("CustomBuild")
+ << attrTag("Include",Option::fixPathToLocalOS(info.file))
+ << attrTagS("Filter", filtername);
+
+ xml << tag("CustomBuild")
+ << attrTag("Include",Option::fixPathToLocalOS(info.file));
+ } else {
+
+ xmlFilter << tag("CustomBuild")
+ << attrTag("Include",Option::fixPathToLocalOS(info.file))
+ << attrTagS("Filter", filtername);
+
+ xml << tag("CustomBuild")
+ << attrTag("Include",Option::fixPathToLocalOS(info.file));
+ }
+
+ } else if(filtername.startsWith("Root Files")) {
+
+ if (info.file.endsWith(".rc")) {
+
+ xmlFilter << tag("ResourceCompile")
+ << attrTag("Include",Option::fixPathToLocalOS(info.file));
+
+ xml << tag("ResourceCompile")
+ << attrTag("Include",Option::fixPathToLocalOS(info.file));
+ }
+ } else {
+
+ xmlFilter << tag("None")
+ << attrTag("Include",Option::fixPathToLocalOS(info.file))
+ << attrTagS("Filter", filtername);
+
+ xml << tag("None")
+ << attrTag("Include",Option::fixPathToLocalOS(info.file));
+ }
+ }
+
+ xml << closetag();
+ xmlFilter << closetag();
+}
+
+bool VCXProjectWriter::outputFileConfig(VCFilter &filter, XmlOutput &xml, XmlOutput &xmlFilter, const QString &filename, const QString &filtername, bool fileAllreadyAdded)
+{
+ bool fileAdded = false;
+
+ // Clearing each filter tool
+ filter.useCustomBuildTool = false;
+ filter.useCompilerTool = false;
+ filter.CustomBuildTool = VCCustomBuildTool();
+ filter.CompilerTool = VCCLCompilerTool();
+
+ // Unset some default options
+ filter.CustomBuildTool.config = filter.Config;
+ filter.CompilerTool.BufferSecurityCheck = unset;
+ filter.CompilerTool.DebugInformationFormat = debugUnknown;
+ filter.CompilerTool.ExceptionHandling = ehDefault;
+ filter.CompilerTool.ProgramDataBaseFileName.clear();
+ filter.CompilerTool.RuntimeLibrary = rtUnknown;
+ filter.CompilerTool.config = filter.Config;
+
+ bool inBuild = false;
+ VCFilterFile info;
+ for (int i = 0; i < filter.Files.count(); ++i) {
+ if (filter.Files.at(i).file == filename) {
+ info = filter.Files.at(i);
+ inBuild = true;
+ }
+ }
+ inBuild &= !info.excludeFromBuild;
+
+ if (inBuild) {
+ filter.addExtraCompiler(info);
+ if (filter.Project->usePCH)
+ filter.modifyPCHstage(info.file);
+ } else {
+ // Excluded files uses an empty compiler stage
+ if(info.excludeFromBuild)
+ filter.useCompilerTool = true;
+ }
+
+ // Actual XML output ----------------------------------
+ if (filter.useCustomBuildTool || filter.useCompilerTool || !inBuild) {
+
+ if (filter.useCustomBuildTool)
+ {
+ if ( !fileAllreadyAdded ) {
+
+ fileAdded = true;
+
+ xmlFilter << tag("CustomBuild")
+ << attrTag("Include",Option::fixPathToLocalOS(filename))
+ << attrTagS("Filter", filtername);
+
+ xml << tag("CustomBuild")
+ << attrTag("Include",Option::fixPathToLocalOS(filename));
+
+ if ( filtername.startsWith("Form Files") || filtername.startsWith("Generated Files") || filtername.startsWith("Resource Files") )
+ xml << attrTagS("FileType", "Document");
+ }
+
+ filter.Project->projectWriter->write(xml, filter.CustomBuildTool);
+ }
+
+ if ( !fileAdded && !fileAllreadyAdded )
+ {
+ fileAdded = true;
+
+ if (filtername.startsWith("Source Files")) {
+
+ xmlFilter << tag("ClCompile")
+ << attrTag("Include",Option::fixPathToLocalOS(filename))
+ << attrTagS("Filter", filtername);
+
+ xml << tag("ClCompile")
+ << attrTag("Include",Option::fixPathToLocalOS(filename));
+
+ } else if(filtername.startsWith("Header Files")) {
+
+ xmlFilter << tag("ClInclude")
+ << attrTag("Include",Option::fixPathToLocalOS(filename))
+ << attrTagS("Filter", filtername);
+
+ xml << tag("ClInclude")
+ << attrTag("Include",Option::fixPathToLocalOS(filename));
+ } else if(filtername.startsWith("Generated Files") || filtername.startsWith("Form Files")) {
+
+ if (filename.endsWith(".h")) {
+
+ xmlFilter << tag("ClInclude")
+ << attrTag("Include",Option::fixPathToLocalOS(filename))
+ << attrTagS("Filter", filtername);
+
+ xml << tag("ClInclude")
+ << attrTag("Include",Option::fixPathToLocalOS(filename));
+ } else if(filename.endsWith(".cpp")) {
+
+ xmlFilter << tag("ClCompile")
+ << attrTag("Include",Option::fixPathToLocalOS(filename))
+ << attrTagS("Filter", filtername);
+
+ xml << tag("ClCompile")
+ << attrTag("Include",Option::fixPathToLocalOS(filename));
+ } else if(filename.endsWith(".res")) {
+
+ xmlFilter << tag("CustomBuild")
+ << attrTag("Include",Option::fixPathToLocalOS(filename))
+ << attrTagS("Filter", filtername);
+
+ xml << tag("CustomBuild")
+ << attrTag("Include",Option::fixPathToLocalOS(filename));
+ } else {
+
+ xmlFilter << tag("CustomBuild")
+ << attrTag("Include",Option::fixPathToLocalOS(filename))
+ << attrTagS("Filter", filtername);
+
+ xml << tag("CustomBuild")
+ << attrTag("Include",Option::fixPathToLocalOS(filename));
+ }
+ } else if(filtername.startsWith("Root Files")) {
+
+ if (filename.endsWith(".rc")) {
+
+ xmlFilter << tag("ResourceCompile")
+ << attrTag("Include",Option::fixPathToLocalOS(filename));
+
+ xml << tag("ResourceCompile")
+ << attrTag("Include",Option::fixPathToLocalOS(filename));
+ }
+ }
+ }
+
+ if(!inBuild) {
+
+ xml << tag("ExcludedFromBuild")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(filter.Config->Name))
+ << valueTag("true");
+ }
+
+ if (filter.useCompilerTool) {
+
+ if ( !filter.CompilerTool.ForcedIncludeFiles.isEmpty() ) {
+ xml << tag("ForcedIncludeFiles")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(filter.Config->Name))
+ << valueTagX(filter.CompilerTool.ForcedIncludeFiles);
+ }
+
+ if ( !filter.CompilerTool.PrecompiledHeaderThrough.isEmpty() ) {
+
+ xml << tag("PrecompiledHeaderFile")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(filter.Config->Name))
+ << valueTag(filter.CompilerTool.PrecompiledHeaderThrough)
+ << tag("PrecompiledHeader")
+ << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(filter.Config->Name))
+ << valueTag(toString(filter.CompilerTool.UsePrecompiledHeader));
+ }
+ }
+ }
+
+ return fileAdded;
+}
+
+QT_END_NAMESPACE
diff --git a/qmake/generators/win32/msbuild_objectmodel.h b/qmake/generators/win32/msbuild_objectmodel.h
new file mode 100644
index 0000000000..c80a2708fa
--- /dev/null
+++ b/qmake/generators/win32/msbuild_objectmodel.h
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the qmake application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MSBUILD_OBJECTMODEL_H
+#define MSBUILD_OBJECTMODEL_H
+
+#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
+
+// Tree & Flat view of files --------------------------------------------------
+class XNode
+{
+public:
+ virtual ~XNode() { }
+ void addElement(const VCFilterFile &file) {
+ addElement(file.file, file);
+ }
+ virtual void addElement(const QString &filepath, const VCFilterFile &allInfo) = 0;
+ virtual void removeElements()= 0;
+ virtual void generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &tagName, VCProject &tool, const QString &filter) = 0;
+ virtual bool hasElements() = 0;
+};
+
+class XTreeNode : public XNode
+{
+ typedef QMap<QString, XTreeNode*> ChildrenMap;
+ VCFilterFile info;
+ ChildrenMap children;
+
+public:
+ virtual ~XTreeNode() { removeElements(); }
+
+ int pathIndex(const QString &filepath) {
+ int Windex = filepath.indexOf("\\");
+ int Uindex = filepath.indexOf("/");
+ if (Windex != -1 && Uindex != -1)
+ return qMin(Windex, Uindex);
+ else if (Windex != -1)
+ return Windex;
+ return Uindex;
+ }
+
+ void addElement(const QString &filepath, const VCFilterFile &allInfo){
+ QString newNodeName(filepath);
+
+ int index = pathIndex(filepath);
+ if (index != -1)
+ newNodeName = filepath.left(index);
+
+ XTreeNode *n = children.value(newNodeName);
+ if (!n) {
+ n = new XTreeNode;
+ n->info = allInfo;
+ children.insert(newNodeName, n);
+ }
+ if (index != -1)
+ n->addElement(filepath.mid(index+1), allInfo);
+ }
+
+ void removeElements() {
+ ChildrenMap::ConstIterator it = children.constBegin();
+ ChildrenMap::ConstIterator end = children.constEnd();
+ for( ; it != end; it++) {
+ (*it)->removeElements();
+ delete it.value();
+ }
+ children.clear();
+ }
+
+ void generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &tagName, VCProject &tool, const QString &filter);
+ bool hasElements() {
+ return children.size() != 0;
+ }
+};
+
+class XFlatNode : public XNode
+{
+ typedef QMap<QString, VCFilterFile> ChildrenMapFlat;
+ ChildrenMapFlat children;
+
+public:
+ virtual ~XFlatNode() { removeElements(); }
+
+ int pathIndex(const QString &filepath) {
+ int Windex = filepath.lastIndexOf("\\");
+ int Uindex = filepath.lastIndexOf("/");
+ if (Windex != -1 && Uindex != -1)
+ return qMax(Windex, Uindex);
+ else if (Windex != -1)
+ return Windex;
+ return Uindex;
+ }
+
+ void addElement(const QString &filepath, const VCFilterFile &allInfo){
+ QString newKey(filepath);
+
+ int index = pathIndex(filepath);
+ if (index != -1)
+ newKey = filepath.mid(index+1);
+
+ // Key designed to sort files with same
+ // name in different paths correctly
+ children.insert(newKey + "\0" + allInfo.file, allInfo);
+ }
+
+ void removeElements() {
+ children.clear();
+ }
+
+ void generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &tagName, VCProject &proj, const QString &filter);
+ bool hasElements() {
+ return children.size() != 0;
+ }
+};
+
+class VCXProjectWriter : public VCProjectWriter
+{
+public:
+ void write(XmlOutput &, VCProjectSingleConfig &);
+ void write(XmlOutput &, VCProject &);
+
+ void write(XmlOutput &, const VCCLCompilerTool &);
+ void write(XmlOutput &, const VCLinkerTool &);
+ void write(XmlOutput &, const VCMIDLTool &);
+ void write(XmlOutput &, const VCCustomBuildTool &);
+ void write(XmlOutput &, const VCLibrarianTool &);
+ void write(XmlOutput &, const VCResourceCompilerTool &);
+ void write(XmlOutput &, const VCEventTool &);
+ void write(XmlOutput &, const VCDeploymentTool &);
+ void write(XmlOutput &, const VCConfiguration &);
+ void write(XmlOutput &, VCFilter &);
+
+private:
+ static void addFilters(VCProject &project, XmlOutput &xmlFilter, const QString &filterName);
+ static void outputFilter(VCProject &project, XmlOutput &xml, XmlOutput &xmlFilter, const QString &filtername);
+ static void outputFileConfigs(VCProject &project, XmlOutput &xml, XmlOutput &xmlFilter, const VCFilterFile &info, const QString &filtername);
+ static bool outputFileConfig(VCFilter &filter, XmlOutput &xml, XmlOutput &xmlFilter, const QString &filename, const QString &filtername, bool fileAllreadyAdded);
+
+ friend class XTreeNode;
+ friend class XFlatNode;
+};
+
+QT_END_NAMESPACE
+
+#endif // MSVC_OBJECTMODEL_H
diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp
new file mode 100644
index 0000000000..c55806d002
--- /dev/null
+++ b/qmake/generators/win32/msvc_nmake.cpp
@@ -0,0 +1,361 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the qmake application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "msvc_nmake.h"
+#include "option.h"
+#include <qregexp.h>
+#include <qhash.h>
+#include <qdir.h>
+#include <time.h>
+
+QT_BEGIN_NAMESPACE
+
+NmakeMakefileGenerator::NmakeMakefileGenerator() : Win32MakefileGenerator(), init_flag(false)
+{
+
+}
+
+bool
+NmakeMakefileGenerator::writeMakefile(QTextStream &t)
+{
+ writeHeader(t);
+ if(!project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty()) {
+ QStringList &qut = project->values("QMAKE_EXTRA_TARGETS");
+ for(QStringList::ConstIterator it = qut.begin(); it != qut.end(); ++it)
+ t << *it << " ";
+ t << "all first clean:" << "\n\t"
+ << "@echo \"Some of the required modules ("
+ << var("QMAKE_FAILED_REQUIREMENTS") << ") are not available.\"" << "\n\t"
+ << "@echo \"Skipped.\"" << endl << endl;
+ writeMakeQmake(t);
+ return true;
+ }
+
+ if(project->first("TEMPLATE") == "app" ||
+ project->first("TEMPLATE") == "lib") {
+#if 0
+ if(Option::mkfile::do_stub_makefile)
+ return MakefileGenerator::writeStubMakefile(t);
+#endif
+ writeNmakeParts(t);
+ return MakefileGenerator::writeMakefile(t);
+ }
+ else if(project->first("TEMPLATE") == "subdirs") {
+ writeSubDirs(t);
+ return true;
+ }
+ return false;
+}
+
+QString NmakeMakefileGenerator::getPdbTarget()
+{
+ return QString(project->first("TARGET") + project->first("TARGET_VERSION_EXT") + ".pdb");
+}
+
+QString NmakeMakefileGenerator::defaultInstall(const QString &t)
+{
+ if((t != "target" && t != "dlltarget") ||
+ (t == "dlltarget" && (project->first("TEMPLATE") != "lib" || !project->isActiveConfig("shared"))) ||
+ project->first("TEMPLATE") == "subdirs")
+ return QString();
+
+ QString ret = Win32MakefileGenerator::defaultInstall(t);
+
+ const QString root = "$(INSTALL_ROOT)";
+ QStringList &uninst = project->values(t + ".uninstall");
+ QString targetdir = Option::fixPathToTargetOS(project->first(t + ".path"), false);
+ targetdir = fileFixify(targetdir, FileFixifyAbsolute);
+ if(targetdir.right(1) != Option::dir_sep)
+ targetdir += Option::dir_sep;
+
+ if(t == "target" && project->first("TEMPLATE") == "lib") {
+ if(project->isActiveConfig("shared") && project->isActiveConfig("debug")) {
+ QString pdb_target = getPdbTarget();
+ pdb_target.remove('"');
+ QString src_targ = (project->isEmpty("DESTDIR") ? QString("$(DESTDIR)") : project->first("DESTDIR")) + pdb_target;
+ QString dst_targ = filePrefixRoot(root, fileFixify(targetdir + pdb_target, FileFixifyAbsolute));
+ if(!ret.isEmpty())
+ ret += "\n\t";
+ ret += QString("-$(INSTALL_FILE)") + " \"" + src_targ + "\" \"" + dst_targ + "\"";
+ if(!uninst.isEmpty())
+ uninst.append("\n\t");
+ uninst.append("-$(DEL_FILE) \"" + dst_targ + "\"");
+ }
+ }
+
+ return ret;
+}
+
+QStringList &NmakeMakefileGenerator::findDependencies(const QString &file)
+{
+ QStringList &aList = MakefileGenerator::findDependencies(file);
+ // Note: The QMAKE_IMAGE_COLLECTION file have all images
+ // as dependency, so don't add precompiled header then
+ if (file == project->first("QMAKE_IMAGE_COLLECTION"))
+ return aList;
+ for(QStringList::Iterator it = Option::cpp_ext.begin(); it != Option::cpp_ext.end(); ++it) {
+ if(file.endsWith(*it)) {
+ if(!precompObj.isEmpty() && !aList.contains(precompObj))
+ aList += precompObj;
+ break;
+ }
+ }
+ return aList;
+}
+
+void NmakeMakefileGenerator::writeNmakeParts(QTextStream &t)
+{
+ writeStandardParts(t);
+
+ // precompiled header
+ if(usePCH) {
+ QString precompRule = QString("-c -Yc -Fp%1 -Fo%2").arg(precompPch).arg(precompObj);
+ t << precompObj << ": " << precompH << " " << findDependencies(precompH).join(" \\\n\t\t")
+ << "\n\t" << "$(CXX) " + precompRule +" $(CXXFLAGS) $(INCPATH) -TP " << precompH << endl << endl;
+ }
+}
+
+QString NmakeMakefileGenerator::var(const QString &value)
+{
+ if (usePCH) {
+ if ((value == "QMAKE_RUN_CXX_IMP_BATCH"
+ || value == "QMAKE_RUN_CXX_IMP"
+ || value == "QMAKE_RUN_CXX")) {
+ QFileInfo precompHInfo(fileInfo(precompH));
+ QString precompRule = QString("-c -FI%1 -Yu%2 -Fp%3")
+ .arg(precompHInfo.fileName())
+ .arg(precompHInfo.fileName())
+ .arg(precompPch);
+ QString p = MakefileGenerator::var(value);
+ p.replace("-c", precompRule);
+ // Cannot use -Gm with -FI & -Yu, as this gives an
+ // internal compiler error, on the newer compilers
+ // ### work-around for a VS 2003 bug. Move to some prf file or remove completely.
+ p.remove("-Gm");
+ return p;
+ } else if (value == "QMAKE_CXXFLAGS") {
+ // Remove internal compiler error option
+ // ### work-around for a VS 2003 bug. Move to some prf file or remove completely.
+ return MakefileGenerator::var(value).remove("-Gm");
+ }
+ }
+
+ // Normal val
+ return MakefileGenerator::var(value);
+}
+
+void NmakeMakefileGenerator::init()
+{
+ if(init_flag)
+ return;
+ init_flag = true;
+
+ /* this should probably not be here, but I'm using it to wrap the .t files */
+ if(project->first("TEMPLATE") == "app")
+ project->values("QMAKE_APP_FLAG").append("1");
+ else if(project->first("TEMPLATE") == "lib")
+ project->values("QMAKE_LIB_FLAG").append("1");
+ else if(project->first("TEMPLATE") == "subdirs") {
+ MakefileGenerator::init();
+ if(project->values("MAKEFILE").isEmpty())
+ project->values("MAKEFILE").append("Makefile");
+ if(project->isEmpty("QMAKE_COPY_FILE"))
+ project->values("QMAKE_COPY_FILE").append("$(COPY)");
+ if(project->isEmpty("QMAKE_COPY_DIR"))
+ project->values("QMAKE_COPY_DIR").append("xcopy /s /q /y /i");
+ if(project->isEmpty("QMAKE_INSTALL_FILE"))
+ project->values("QMAKE_INSTALL_FILE").append("$(COPY_FILE)");
+ if(project->isEmpty("QMAKE_INSTALL_PROGRAM"))
+ project->values("QMAKE_INSTALL_PROGRAM").append("$(COPY_FILE)");
+ if(project->isEmpty("QMAKE_INSTALL_DIR"))
+ project->values("QMAKE_INSTALL_DIR").append("$(COPY_DIR)");
+ return;
+ }
+
+ project->values("QMAKE_LIBS") += escapeFilePaths(project->values("LIBS"));
+ project->values("QMAKE_LIBS_PRIVATE") += escapeFilePaths(project->values("LIBS_PRIVATE"));
+ processVars();
+
+ if (!project->values("RES_FILE").isEmpty()) {
+ project->values("QMAKE_LIBS") += escapeFilePaths(project->values("RES_FILE"));
+ }
+
+ if (!project->values("DEF_FILE").isEmpty()) {
+ QString defFileName = fileFixify(project->values("DEF_FILE")).first();
+ project->values("QMAKE_LFLAGS").append(QString("/DEF:") + escapeFilePath(defFileName));
+ }
+
+ if(!project->values("VERSION").isEmpty()) {
+ QString version = project->values("VERSION")[0];
+ int firstDot = version.indexOf(".");
+ QString major = version.left(firstDot);
+ QString minor = version.right(version.length() - firstDot - 1);
+ minor.replace(".", "");
+ project->values("QMAKE_LFLAGS").append("/VERSION:" + major + "." + minor);
+ }
+
+ // Base class init!
+ MakefileGenerator::init();
+
+ // Setup PCH variables
+ precompH = project->first("PRECOMPILED_HEADER");
+ usePCH = !precompH.isEmpty() && project->isActiveConfig("precompile_header");
+ if (usePCH) {
+ // Created files
+ precompObj = var("PRECOMPILED_DIR") + project->first("TARGET") + "_pch" + Option::obj_ext;
+ precompPch = var("PRECOMPILED_DIR") + project->first("TARGET") + "_pch.pch";
+ // Add linking of precompObj (required for whole precompiled classes)
+ project->values("OBJECTS") += precompObj;
+ // Add pch file to cleanup
+ project->values("QMAKE_CLEAN") += precompPch;
+ // Return to variable pool
+ project->values("PRECOMPILED_OBJECT") = QStringList(precompObj);
+ project->values("PRECOMPILED_PCH") = QStringList(precompPch);
+ }
+
+ QString version = project->first("TARGET_VERSION_EXT");
+ if(project->isActiveConfig("shared")) {
+ project->values("QMAKE_CLEAN").append(project->first("DESTDIR") + project->first("TARGET") + version + ".exp");
+ }
+ if(project->isActiveConfig("debug")) {
+ project->values("QMAKE_DISTCLEAN").append(project->first("DESTDIR") + project->first("TARGET") + version + ".pdb");
+ project->values("QMAKE_CLEAN").append(project->first("DESTDIR") + project->first("TARGET") + version + ".ilk");
+ project->values("QMAKE_CLEAN").append("vc*.pdb");
+ project->values("QMAKE_CLEAN").append("vc*.idb");
+ }
+}
+
+void NmakeMakefileGenerator::writeLibDirPart(QTextStream &t)
+{
+ QStringList libDirs = project->values("QMAKE_LIBDIR");
+ for (int i = 0; i < libDirs.size(); ++i)
+ libDirs[i].remove("\"");
+ t << valGlue(libDirs,"/LIBPATH:\"","\" /LIBPATH:\"","\"") << " ";
+}
+
+void NmakeMakefileGenerator::writeImplicitRulesPart(QTextStream &t)
+{
+ t << ".SUFFIXES:";
+ for(QStringList::Iterator cit = Option::c_ext.begin(); cit != Option::c_ext.end(); ++cit)
+ t << " " << (*cit);
+ for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit)
+ t << " " << (*cppit);
+ t << endl << endl;
+
+ if(!project->isActiveConfig("no_batch")) {
+ // Batchmode doesn't use the non implicit rules QMAKE_RUN_CXX & QMAKE_RUN_CC
+ project->variables().remove("QMAKE_RUN_CXX");
+ project->variables().remove("QMAKE_RUN_CC");
+
+ QHash<QString, void*> source_directories;
+ source_directories.insert(".", (void*)1);
+ QString directories[] = { QString("UI_SOURCES_DIR"), QString("UI_DIR"), QString() };
+ for(int y = 0; !directories[y].isNull(); y++) {
+ QString dirTemp = project->first(directories[y]);
+ if (dirTemp.endsWith("\\"))
+ dirTemp.truncate(dirTemp.length()-1);
+ if(!dirTemp.isEmpty())
+ source_directories.insert(dirTemp, (void*)1);
+ }
+ QString srcs[] = { QString("SOURCES"), QString("GENERATED_SOURCES"), QString() };
+ for(int x = 0; !srcs[x].isNull(); x++) {
+ QStringList &l = project->values(srcs[x]);
+ for(QStringList::Iterator sit = l.begin(); sit != l.end(); ++sit) {
+ QString sep = "\\";
+ if((*sit).indexOf(sep) == -1)
+ sep = "/";
+ QString dir = (*sit).section(sep, 0, -2);
+ if(!dir.isEmpty() && !source_directories[dir])
+ source_directories.insert(dir, (void*)1);
+ }
+ }
+
+ for(QHash<QString, void*>::Iterator it(source_directories.begin()); it != source_directories.end(); ++it) {
+ if(it.key().isEmpty())
+ continue;
+ QString objDir = var("OBJECTS_DIR");
+ if (objDir == ".\\")
+ objDir = "";
+ for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit)
+ t << "{" << it.key() << "}" << (*cppit) << "{" << objDir << "}" << Option::obj_ext << "::\n\t"
+ << var("QMAKE_RUN_CXX_IMP_BATCH").replace(QRegExp("\\$@"), var("OBJECTS_DIR")) << endl << "\t$<" << endl << "<<" << endl << endl;
+ for(QStringList::Iterator cit = Option::c_ext.begin(); cit != Option::c_ext.end(); ++cit)
+ t << "{" << it.key() << "}" << (*cit) << "{" << objDir << "}" << Option::obj_ext << "::\n\t"
+ << var("QMAKE_RUN_CC_IMP_BATCH").replace(QRegExp("\\$@"), var("OBJECTS_DIR")) << endl << "\t$<" << endl << "<<" << endl << endl;
+ }
+ } else {
+ for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit)
+ t << (*cppit) << Option::obj_ext << ":\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl;
+ for(QStringList::Iterator cit = Option::c_ext.begin(); cit != Option::c_ext.end(); ++cit)
+ t << (*cit) << Option::obj_ext << ":\n\t" << var("QMAKE_RUN_CC_IMP") << endl << endl;
+ }
+
+}
+
+void NmakeMakefileGenerator::writeBuildRulesPart(QTextStream &t)
+{
+ t << "first: all" << endl;
+ t << "all: " << fileFixify(Option::output.fileName()) << " " << varGlue("ALL_DEPS"," "," "," ") << "$(DESTDIR_TARGET)" << endl << endl;
+ t << "$(DESTDIR_TARGET): " << var("PRE_TARGETDEPS") << " $(OBJECTS) " << var("POST_TARGETDEPS");
+
+ if(!project->isEmpty("QMAKE_PRE_LINK"))
+ t << "\n\t" <<var("QMAKE_PRE_LINK");
+ if(project->isActiveConfig("staticlib")) {
+ t << "\n\t" << "$(LIBAPP) $(LIBFLAGS) /OUT:$(DESTDIR_TARGET) @<<" << "\n\t "
+ << "$(OBJECTS)";
+ } else {
+ t << "\n\t" << "$(LINK) $(LFLAGS) /OUT:$(DESTDIR_TARGET) @<< " << "\n\t "
+ << "$(OBJECTS) $(LIBS)";
+ }
+ t << endl << "<<";
+ QString signature = !project->isEmpty("SIGNATURE_FILE") ? var("SIGNATURE_FILE") : var("DEFAULT_SIGNATURE");
+ bool useSignature = !signature.isEmpty() && !project->isActiveConfig("staticlib") &&
+ !project->isEmpty("CE_SDK") && !project->isEmpty("CE_ARCH");
+ if(useSignature) {
+ t << "\n\tsigntool sign /F " << signature << " $(DESTDIR_TARGET)";
+ }
+ if(!project->isEmpty("QMAKE_POST_LINK")) {
+ t << "\n\t" << var("QMAKE_POST_LINK");
+ }
+ t << endl;
+}
+
+QT_END_NAMESPACE
diff --git a/qmake/generators/win32/msvc_nmake.h b/qmake/generators/win32/msvc_nmake.h
new file mode 100644
index 0000000000..8954655672
--- /dev/null
+++ b/qmake/generators/win32/msvc_nmake.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the qmake application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MSVC_NMAKE_H
+#define MSVC_NMAKE_H
+
+#include "winmakefile.h"
+
+QT_BEGIN_NAMESPACE
+
+class NmakeMakefileGenerator : public Win32MakefileGenerator
+{
+ bool init_flag;
+ void writeNmakeParts(QTextStream &);
+ void writeLibDirPart(QTextStream &t);
+ bool writeMakefile(QTextStream &);
+ void writeImplicitRulesPart(QTextStream &t);
+ void writeBuildRulesPart(QTextStream &t);
+ void init();
+
+protected:
+ virtual QString getPdbTarget();
+ virtual QString defaultInstall(const QString &t);
+ virtual QStringList &findDependencies(const QString &file);
+ QString var(const QString &value);
+ QString precompH, precompObj, precompPch;
+ bool usePCH;
+
+public:
+ NmakeMakefileGenerator();
+ ~NmakeMakefileGenerator();
+
+};
+
+inline NmakeMakefileGenerator::~NmakeMakefileGenerator()
+{ }
+
+QT_END_NAMESPACE
+
+#endif // MSVC_NMAKE_H
diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp
new file mode 100644
index 0000000000..88a5043519
--- /dev/null
+++ b/qmake/generators/win32/msvc_objectmodel.cpp
@@ -0,0 +1,2909 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the qmake application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "msvc_objectmodel.h"
+#include "msvc_vcproj.h"
+#include "msvc_vcxproj.h"
+#include <qstringlist.h>
+#include <qfileinfo.h>
+
+QT_BEGIN_NAMESPACE
+
+// XML Tags ---------------------------------------------------------
+const char _Configuration[] = "Configuration";
+const char _Configurations[] = "Configurations";
+const char q_File[] = "File";
+const char _FileConfiguration[] = "FileConfiguration";
+const char q_Files[] = "Files";
+const char _Filter[] = "Filter";
+const char _Globals[] = "Globals";
+const char _Platform[] = "Platform";
+const char _Platforms[] = "Platforms";
+const char _Tool[] = "Tool";
+const char _VisualStudioProject[] = "VisualStudioProject";
+
+// XML Properties ---------------------------------------------------
+const char _AddModuleNamesToAssembly[] = "AddModuleNamesToAssembly";
+const char _AdditionalDependencies[] = "AdditionalDependencies";
+const char _AdditionalFiles[] = "AdditionalFiles";
+const char _AdditionalIncludeDirectories[] = "AdditionalIncludeDirectories";
+const char _AdditionalLibraryDirectories[] = "AdditionalLibraryDirectories";
+const char _AdditionalOptions[] = "AdditionalOptions";
+const char _AdditionalUsingDirectories[] = "AdditionalUsingDirectories";
+const char _AssemblerListingLocation[] = "AssemblerListingLocation";
+const char _AssemblerOutput[] = "AssemblerOutput";
+const char _ATLMinimizesCRunTimeLibraryUsage[] = "ATLMinimizesCRunTimeLibraryUsage";
+const char _BaseAddress[] = "BaseAddress";
+const char _BasicRuntimeChecks[] = "BasicRuntimeChecks";
+const char _BrowseInformation[] = "BrowseInformation";
+const char _BrowseInformationFile[] = "BrowseInformationFile";
+const char _BufferSecurityCheck[] = "BufferSecurityCheck";
+const char _BuildBrowserInformation[] = "BuildBrowserInformation";
+const char _CPreprocessOptions[] = "CPreprocessOptions";
+const char _CallingConvention[] = "CallingConvention";
+const char _CharacterSet[] = "CharacterSet";
+const char _CommandLine[] = "CommandLine";
+const char _CompileAs[] = "CompileAs";
+const char _CompileAsManaged[] = "CompileAsManaged";
+const char _CompileOnly[] = "CompileOnly";
+const char _ConfigurationType[] = "ConfigurationType";
+const char _Culture[] = "Culture";
+const char _DLLDataFileName[] = "DLLDataFileName";
+const char _DebugInformationFormat[] = "DebugInformationFormat";
+const char _DefaultCharIsUnsigned[] = "DefaultCharIsUnsigned";
+const char _DefaultCharType[] = "DefaultCharType";
+const char _DelayLoadDLLs[] = "DelayLoadDLLs";
+const char _DeleteExtensionsOnClean[] = "DeleteExtensionsOnClean";
+const char _Description[] = "Description";
+const char _Detect64BitPortabilityProblems[] = "Detect64BitPortabilityProblems";
+const char _DisableLanguageExtensions[] = "DisableLanguageExtensions";
+const char _DisableSpecificWarnings[] = "DisableSpecificWarnings";
+const char _EnableCOMDATFolding[] = "EnableCOMDATFolding";
+const char _EnableErrorChecks[] = "EnableErrorChecks";
+const char _EnableEnhancedInstructionSet[] = "EnableEnhancedInstructionSet";
+const char _EnableFiberSafeOptimizations[] = "EnableFiberSafeOptimizations";
+const char _EnableFunctionLevelLinking[] = "EnableFunctionLevelLinking";
+const char _EnableIntrinsicFunctions[] = "EnableIntrinsicFunctions";
+const char _EntryPointSymbol[] = "EntryPointSymbol";
+const char _ErrorCheckAllocations[] = "ErrorCheckAllocations";
+const char _ErrorCheckBounds[] = "ErrorCheckBounds";
+const char _ErrorCheckEnumRange[] = "ErrorCheckEnumRange";
+const char _ErrorCheckRefPointers[] = "ErrorCheckRefPointers";
+const char _ErrorCheckStubData[] = "ErrorCheckStubData";
+const char _ExceptionHandling[] = "ExceptionHandling";
+const char _ExcludedFromBuild[] = "ExcludedFromBuild";
+const char _ExpandAttributedSource[] = "ExpandAttributedSource";
+const char _ExportNamedFunctions[] = "ExportNamedFunctions";
+const char _FavorSizeOrSpeed[] = "FavorSizeOrSpeed";
+const char _FloatingPointModel[] = "FloatingPointModel";
+const char _FloatingPointExceptions[] = "FloatingPointExceptions";
+const char _ForceConformanceInForLoopScope[] = "ForceConformanceInForLoopScope";
+const char _ForceSymbolReferences[] = "ForceSymbolReferences";
+const char _ForcedIncludeFiles[] = "ForcedIncludeFiles";
+const char _ForcedUsingFiles[] = "ForcedUsingFiles";
+const char _FullIncludePath[] = "FullIncludePath";
+const char _FunctionOrder[] = "FunctionOrder";
+const char _GenerateDebugInformation[] = "GenerateDebugInformation";
+const char _GenerateMapFile[] = "GenerateMapFile";
+const char _GeneratePreprocessedFile[] = "GeneratePreprocessedFile";
+const char _GenerateStublessProxies[] = "GenerateStublessProxies";
+const char _GenerateTypeLibrary[] = "GenerateTypeLibrary";
+const char _GlobalOptimizations[] = "GlobalOptimizations";
+const char _HeaderFileName[] = "HeaderFileName";
+const char _HeapCommitSize[] = "HeapCommitSize";
+const char _HeapReserveSize[] = "HeapReserveSize";
+const char _IgnoreAllDefaultLibraries[] = "IgnoreAllDefaultLibraries";
+const char _IgnoreDefaultLibraryNames[] = "IgnoreDefaultLibraryNames";
+const char _IgnoreEmbeddedIDL[] = "IgnoreEmbeddedIDL";
+const char _IgnoreImportLibrary[] = "IgnoreImportLibrary";
+const char _IgnoreStandardIncludePath[] = "IgnoreStandardIncludePath";
+const char _ImportLibrary[] = "ImportLibrary";
+const char _ImproveFloatingPointConsistency[] = "ImproveFloatingPointConsistency";
+const char _InlineFunctionExpansion[] = "InlineFunctionExpansion";
+const char _InterfaceIdentifierFileName[] = "InterfaceIdentifierFileName";
+const char _IntermediateDirectory[] = "IntermediateDirectory";
+const char _KeepComments[] = "KeepComments";
+const char _LargeAddressAware[] = "LargeAddressAware";
+const char _LinkDLL[] = "LinkDLL";
+const char _LinkIncremental[] = "LinkIncremental";
+const char _LinkTimeCodeGeneration[] = "LinkTimeCodeGeneration";
+const char _LinkToManagedResourceFile[] = "LinkToManagedResourceFile";
+const char _MapExports[] = "MapExports";
+const char _MapFileName[] = "MapFileName";
+const char _MapLines[] = "MapLines ";
+const char _MergeSections[] = "MergeSections";
+const char _MergedIDLBaseFileName[] = "MergedIDLBaseFileName";
+const char _MidlCommandFile[] = "MidlCommandFile";
+const char _MinimalRebuild[] = "MinimalRebuild";
+const char _MkTypLibCompatible[] = "MkTypLibCompatible";
+const char _ModuleDefinitionFile[] = "ModuleDefinitionFile";
+const char _Name[] = "Name";
+const char _ObjectFile[] = "ObjectFile";
+const char _OmitFramePointers[] = "OmitFramePointers";
+const char _OpenMP[] = "OpenMP";
+const char _Optimization[] = "Optimization ";
+const char _OptimizeForProcessor[] = "OptimizeForProcessor";
+const char _OptimizeForWindows98[] = "OptimizeForWindows98";
+const char _OptimizeForWindowsApplication[] = "OptimizeForWindowsApplication";
+const char _OptimizeReferences[] = "OptimizeReferences";
+const char _OutputDirectory[] = "OutputDirectory";
+const char _OutputFile[] = "OutputFile";
+const char _Outputs[] = "Outputs";
+const char _ParseFiles[] = "ParseFiles";
+const char _PrecompiledHeaderFile[] = "PrecompiledHeaderFile";
+const char _PrecompiledHeaderThrough[] = "PrecompiledHeaderThrough";
+const char _PreprocessorDefinitions[] = "PreprocessorDefinitions";
+const char _PrimaryOutput[] = "PrimaryOutput";
+const char _ProjectGUID[] = "ProjectGUID";
+const char _Keyword[] = "Keyword";
+const char _ProjectType[] = "ProjectType";
+const char _ProgramDatabase[] = "ProgramDatabase";
+const char _ProgramDataBaseFileName[] = "ProgramDataBaseFileName";
+const char _ProgramDatabaseFile[] = "ProgramDatabaseFile";
+const char _ProxyFileName[] = "ProxyFileName";
+const char _RedirectOutputAndErrors[] = "RedirectOutputAndErrors";
+const char _RegisterOutput[] = "RegisterOutput";
+const char _RelativePath[] = "RelativePath";
+const char _RemoteDirectory[] = "RemoteDirectory";
+const char _ResourceOnlyDLL[] = "ResourceOnlyDLL";
+const char _ResourceOutputFileName[] = "ResourceOutputFileName";
+const char _RuntimeLibrary[] = "RuntimeLibrary";
+const char _RuntimeTypeInfo[] = "RuntimeTypeInfo";
+const char _SccProjectName[] = "SccProjectName";
+const char _SccLocalPath[] = "SccLocalPath";
+const char _SetChecksum[] = "SetChecksum";
+const char _ShowIncludes[] = "ShowIncludes";
+const char _ShowProgress[] = "ShowProgress";
+const char _SmallerTypeCheck[] = "SmallerTypeCheck";
+const char _StackCommitSize[] = "StackCommitSize";
+const char _StackReserveSize[] = "StackReserveSize";
+const char _StringPooling[] = "StringPooling";
+const char _StripPrivateSymbols[] = "StripPrivateSymbols";
+const char _StructMemberAlignment[] = "StructMemberAlignment";
+const char _SubSystem[] = "SubSystem";
+const char _SupportUnloadOfDelayLoadedDLL[] = "SupportUnloadOfDelayLoadedDLL";
+const char _SuppressStartupBanner[] = "SuppressStartupBanner";
+const char _SwapRunFromCD[] = "SwapRunFromCD";
+const char _SwapRunFromNet[] = "SwapRunFromNet";
+const char _TargetEnvironment[] = "TargetEnvironment";
+const char _TargetMachine[] = "TargetMachine";
+const char _TerminalServerAware[] = "TerminalServerAware";
+const char _Path[] = "Path";
+const char _TreatWChar_tAsBuiltInType[] = "TreatWChar_tAsBuiltInType";
+const char _TurnOffAssemblyGeneration[] = "TurnOffAssemblyGeneration";
+const char _TypeLibraryFile[] = "TypeLibraryFile";
+const char _TypeLibraryName[] = "TypeLibraryName";
+const char _TypeLibraryResourceID[] = "TypeLibraryResourceID";
+const char _UndefineAllPreprocessorDefinitions[]= "UndefineAllPreprocessorDefinitions";
+const char _UndefinePreprocessorDefinitions[] = "UndefinePreprocessorDefinitions";
+const char _UniqueIdentifier[] = "UniqueIdentifier";
+const char _UseOfATL[] = "UseOfATL";
+const char _UseOfMfc[] = "UseOfMfc";
+const char _UsePrecompiledHeader[] = "UsePrecompiledHeader";
+const char _ValidateParameters[] = "ValidateParameters";
+const char _VCCLCompilerTool[] = "VCCLCompilerTool";
+const char _VCLibrarianTool[] = "VCLibrarianTool";
+const char _VCLinkerTool[] = "VCLinkerTool";
+const char _VCCustomBuildTool[] = "VCCustomBuildTool";
+const char _VCResourceCompilerTool[] = "VCResourceCompilerTool";
+const char _VCMIDLTool[] = "VCMIDLTool";
+const char _Version[] = "Version";
+const char _WarnAsError[] = "WarnAsError";
+const char _WarningLevel[] = "WarningLevel";
+const char _WholeProgramOptimization[] = "WholeProgramOptimization";
+const char _CompileForArchitecture[] = "CompileForArchitecture";
+const char _InterworkCalls[] = "InterworkCalls";
+
+// XmlOutput stream functions ------------------------------
+inline XmlOutput::xml_output attrT(const char *name, const triState v)
+{
+ if(v == unset)
+ return noxml();
+ return attr(name, (v == _True ? "true" : "false"));
+}
+
+inline XmlOutput::xml_output attrE(const char *name, int v)
+{
+ return attr(name, QString::number(v));
+}
+
+/*ifNot version*/
+inline XmlOutput::xml_output attrE(const char *name, int v, int ifn)
+{
+ if (v == ifn)
+ return noxml();
+ return attr(name, QString::number(v));
+}
+
+inline XmlOutput::xml_output attrL(const char *name, qint64 v)
+{
+ return attr(name, QString::number(v));
+}
+
+/*ifNot version*/
+inline XmlOutput::xml_output attrL(const char *name, qint64 v, qint64 ifn)
+{
+ if (v == ifn)
+ return noxml();
+ return attr(name, QString::number(v));
+}
+
+inline XmlOutput::xml_output attrS(const char *name, const QString &v)
+{
+ if(v.isEmpty())
+ return noxml();
+ return attr(name, v);
+}
+
+inline XmlOutput::xml_output attrX(const char *name, const QStringList &v, const char *s = ",")
+{
+ if(v.isEmpty())
+ return noxml();
+ return attr(name, v.join(s));
+}
+
+triState operator!(const triState &rhs)
+{
+ if (rhs == unset)
+ return rhs;
+ triState lhs = (rhs == _True ? _False : _True);
+ return lhs;
+}
+
+// VCToolBase -------------------------------------------------
+QStringList VCToolBase::fixCommandLine(const QString &input)
+{
+ // The splitting regexp is a bit bizarre for backwards compat reasons (why else ...).
+ return input.split(QRegExp(QLatin1String("\n\t|\r\\\\h|\r\n")));
+}
+
+static QString vcCommandSeparator()
+{
+ // MSVC transforms the build tree into a single batch file, simply pasting the contents
+ // of the custom commands into it, and putting an "if errorlevel goto" statement behind it.
+ // As we want every sub-command to be error-checked (as is done by makefile-based
+ // backends), we insert the checks ourselves, using the undocumented jump target.
+ static QString cmdSep =
+ QLatin1String("&#x000D;&#x000A;if errorlevel 1 goto VCReportError&#x000D;&#x000A;");
+ return cmdSep;
+}
+
+// VCCLCompilerTool -------------------------------------------------
+VCCLCompilerTool::VCCLCompilerTool()
+ : AssemblerOutput(asmListingNone),
+ BasicRuntimeChecks(runtimeBasicCheckNone),
+ BrowseInformation(brInfoNone),
+ BufferSecurityCheck(_False),
+ CallingConvention(callConventionDefault),
+ CompileAs(compileAsDefault),
+ CompileAsManaged(managedDefault),
+ CompileOnly(unset),
+ DebugInformationFormat(debugDisabled),
+ DefaultCharIsUnsigned(unset),
+ Detect64BitPortabilityProblems(unset),
+ DisableLanguageExtensions(unset),
+ EnableEnhancedInstructionSet(archNotSet),
+ EnableFiberSafeOptimizations(unset),
+ EnableFunctionLevelLinking(unset),
+ EnableIntrinsicFunctions(unset),
+ ExceptionHandling(ehDefault),
+ ExpandAttributedSource(unset),
+ FavorSizeOrSpeed(favorNone),
+ FloatingPointModel(floatingPointNotSet),
+ FloatingPointExceptions(unset),
+ ForceConformanceInForLoopScope(unset),
+ GeneratePreprocessedFile(preprocessNo),
+ PreprocessSuppressLineNumbers(unset),
+ GlobalOptimizations(unset),
+ IgnoreStandardIncludePath(unset),
+ ImproveFloatingPointConsistency(unset),
+ InlineFunctionExpansion(expandDefault),
+ KeepComments(unset),
+ MinimalRebuild(unset),
+ OmitDefaultLibName(unset),
+ OmitFramePointers(unset),
+ OpenMP(unset),
+ Optimization(optimizeCustom),
+ OptimizeForProcessor(procOptimizeBlended),
+ OptimizeForWindowsApplication(unset),
+ ProgramDataBaseFileName(""),
+ RuntimeLibrary(rtMultiThreaded),
+ RuntimeTypeInfo(unset),
+ ShowIncludes(unset),
+ SmallerTypeCheck(unset),
+ StringPooling(unset),
+ StructMemberAlignment(alignNotSet),
+ SuppressStartupBanner(unset),
+ TreatWChar_tAsBuiltInType(unset),
+ TurnOffAssemblyGeneration(unset),
+ UndefineAllPreprocessorDefinitions(unset),
+ UsePrecompiledHeader(pchUnset),
+ UseUnicodeForAssemblerListing(unset),
+ WarnAsError(unset),
+ WarningLevel(warningLevel_0),
+ WholeProgramOptimization(unset),
+ CompileForArchitecture(archUnknown),
+ InterworkCalls(unset),
+ EnablePREfast(unset),
+ DisplayFullPaths(unset),
+ MultiProcessorCompilation(unset),
+ GenerateXMLDocumentationFiles(unset),
+ CreateHotpatchableImage(unset)
+{
+}
+
+/*
+ * Some values for the attribute UsePrecompiledHeader have changed from VS 2003 to VS 2005,
+ * see the following chart, so we need a function that transforms those values if we are
+ * using NET2005:
+ *
+ * Meaning 2003 2005
+ * -----------------------------------------
+ * Don't use PCH 0 0
+ * Create PCH (/Yc) 1 1
+ * Automatically generate (/YX) 2 (seems that it was removed)
+ * Use specific PCH (/Yu) 3 2
+ *
+ */
+inline XmlOutput::xml_output xformUsePrecompiledHeaderForNET2005(pchOption whatPch, DotNET compilerVersion)
+{
+ if (compilerVersion >= NET2005) {
+ if (whatPch == pchGenerateAuto) whatPch = (pchOption)0;
+ if (whatPch == pchUseUsingSpecific) whatPch = (pchOption)2;
+ }
+ return attrE(_UsePrecompiledHeader, whatPch, /*ifNot*/ pchUnset);
+}
+
+inline XmlOutput::xml_output xformExceptionHandlingNET2005(exceptionHandling eh, DotNET compilerVersion)
+{
+ if (eh == ehDefault)
+ return noxml();
+
+ if (compilerVersion >= NET2005)
+ return attrE(_ExceptionHandling, eh);
+
+ return attrS(_ExceptionHandling, (eh == ehNoSEH ? "true" : "false"));
+}
+
+bool VCCLCompilerTool::parseOption(const char* option)
+{
+ // skip index 0 ('/' or '-')
+ char first = option[1];
+ char second = option[2];
+ char third = option[3];
+ char fourth = option[4];
+ bool found = true;
+
+ switch (first) {
+ case '?':
+ case 'h':
+ if(second == 'o' && third == 't' && fourth == 'p') {
+ CreateHotpatchableImage = _True;
+ break;
+ }
+ qWarning("Generator: Option '/?', '/help': MSVC.NET projects do not support outputting help info");
+ found = false;
+ break;
+ case '@':
+ qWarning("Generator: Option '/@': MSVC.NET projects do not support the use of a response file");
+ found = false;
+ break;
+ case 'l':
+ qWarning("Generator: Option '/link': qmake generator does not support passing link options through the compiler tool");
+ found = false;
+ break;
+ case 'A':
+ if(second != 'I') {
+ found = false; break;
+ }
+ AdditionalUsingDirectories += option+3;
+ break;
+ case 'C':
+ KeepComments = _True;
+ break;
+ case 'D':
+ PreprocessorDefinitions += option+2;
+ break;
+ case 'E':
+ if(second == 'H') {
+ QByteArray opt(option + 2);
+ if (opt.contains('a') && !opt.contains('s') && !opt.contains('c'))
+ ExceptionHandling = ehSEH;
+ else if (!opt.contains('a') && opt.contains("s-") && opt.contains("c-"))
+ ExceptionHandling = ehNone;
+ else if (!opt.contains('a') && opt.contains('s') && opt.contains('c'))
+ ExceptionHandling = ehNoSEH;
+ else {
+ // ExceptionHandling must be false, or it will override
+ // with an /EHsc option
+ ExceptionHandling = ehNone;
+ AdditionalOptions += option;
+ }
+ if (config->CompilerVersion < NET2005
+ && ExceptionHandling == ehSEH) {
+ ExceptionHandling = ehNone;
+ AdditionalOptions += option;
+ }
+ break;
+ } else if (second == 'P') {
+ PreprocessSuppressLineNumbers = _True;
+ }
+ GeneratePreprocessedFile = preprocessYes;
+ break;
+ case 'F':
+ if(second <= '9' && second >= '0') {
+ AdditionalOptions += option;
+ break;
+ } else {
+ switch (second) {
+ case 'A':
+ if(third == 'c') {
+ AssemblerOutput = asmListingAsmMachine;
+ if(fourth == 's')
+ AssemblerOutput = asmListingAsmMachineSrc;
+ } else if(third == 's') {
+ AssemblerOutput = asmListingAsmSrc;
+ } else if (third == 'u') {
+ UseUnicodeForAssemblerListing = _True;
+ } else {
+ AssemblerOutput = asmListingAssemblyOnly;
+ }
+ break;
+ case 'C':
+ DisplayFullPaths = _True;
+ break;
+ case 'a':
+ AssemblerListingLocation = option+3;
+ break;
+ case 'I':
+ ForcedIncludeFiles += option+3;
+ break;
+ case 'i':
+ PreprocessOutputPath += option+3;
+ break;
+ case 'R':
+ BrowseInformation = brAllInfo;
+ BrowseInformationFile = option+3;
+ break;
+ case 'r':
+ BrowseInformation = brNoLocalSymbols;
+ BrowseInformationFile = option+3;
+ break;
+ case 'U':
+ ForcedUsingFiles += option+3;
+ break;
+ case 'd':
+ ProgramDataBaseFileName = option+3;
+ break;
+ case 'e':
+ OutputFile = option+3;
+ break;
+ case 'm':
+ AdditionalOptions += option;
+ break;
+ case 'o':
+ ObjectFile = option+3;
+ break;
+ case 'p':
+ PrecompiledHeaderFile = option+3;
+ break;
+ case 'x':
+ ExpandAttributedSource = _True;
+ break;
+ default:
+ found = false; break;
+ }
+ }
+ break;
+ case 'G':
+ switch (second) {
+ case '3':
+ case '4':
+ qWarning("Option '/G3' and '/G4' were phased out in Visual C++ 5.0");
+ found = false; break;
+ case '5':
+ OptimizeForProcessor = procOptimizePentium;
+ break;
+ case '6':
+ case 'B':
+ OptimizeForProcessor = procOptimizePentiumProAndAbove;
+ break;
+ case '7':
+ OptimizeForProcessor = procOptimizePentium4AndAbove;
+ break;
+ case 'A':
+ OptimizeForWindowsApplication = _True;
+ break;
+ case 'F':
+ StringPooling = _True;
+ break;
+ case 'H':
+ AdditionalOptions += option;
+ break;
+ case 'L':
+ WholeProgramOptimization = _True;
+ if(third == '-')
+ WholeProgramOptimization = _False;
+ break;
+ case 'R':
+ RuntimeTypeInfo = _True;
+ if(third == '-')
+ RuntimeTypeInfo = _False;
+ break;
+ case 'S':
+ BufferSecurityCheck = _True;
+ if(third == '-')
+ BufferSecurityCheck = _False;
+ break;
+ case 'T':
+ EnableFiberSafeOptimizations = _True;
+ break;
+ case 'X':
+ // Same as the /EHsc option, which is Exception Handling without SEH
+ ExceptionHandling = ehNoSEH;
+ if (third == '-')
+ ExceptionHandling = ehNone;
+ break;
+ case 'Z':
+ case 'e':
+ case 'h':
+ AdditionalOptions += option;
+ break;
+ case 'd':
+ CallingConvention = callConventionCDecl;
+ break;
+ case 'f':
+ StringPooling = _True;
+ AdditionalOptions += option;
+ break;
+ case 'm':
+ MinimalRebuild = _True;
+ if(third == '-')
+ MinimalRebuild = _False;
+ break;
+ case 'r':
+ CallingConvention = callConventionFastCall;
+ break;
+ case 's':
+ // Warning: following [num] is not used,
+ // were should we put it?
+ BufferSecurityCheck = _True;
+ break;
+ case 'y':
+ EnableFunctionLevelLinking = _True;
+ break;
+ case 'z':
+ CallingConvention = callConventionStdCall;
+ break;
+ default:
+ found = false; break;
+ }
+ break;
+ case 'H':
+ AdditionalOptions += option;
+ break;
+ case 'I':
+ AdditionalIncludeDirectories += option+2;
+ break;
+ case 'J':
+ DefaultCharIsUnsigned = _True;
+ break;
+ case 'L':
+ if(second == 'D') {
+ AdditionalOptions += option;
+ break;
+ }
+ found = false; break;
+ case 'M':
+ if(second == 'D') {
+ RuntimeLibrary = rtMultiThreadedDLL;
+ if(third == 'd')
+ RuntimeLibrary = rtMultiThreadedDebugDLL;
+ break;
+ } else if(second == 'L') {
+ RuntimeLibrary = rtSingleThreaded;
+ if(third == 'd')
+ RuntimeLibrary = rtSingleThreadedDebug;
+ break;
+ } else if(second == 'T') {
+ RuntimeLibrary = rtMultiThreaded;
+ if(third == 'd')
+ RuntimeLibrary = rtMultiThreadedDebug;
+ break;
+ } else if (second == 'P') {
+ if (config->CompilerVersion >= NET2005) {
+ AdditionalOptions += option;
+ } else if (config->CompilerVersion >= NET2010) {
+ MultiProcessorCompilation = _True;
+ MultiProcessorCompilationProcessorCount = option+3;
+ } else {
+ warn_msg(WarnLogic, "/MP option is not supported in Visual C++ < 2005, ignoring.");
+ }
+ break;
+ }
+ found = false; break;
+ case 'O':
+ switch (second) {
+ case '1':
+ Optimization = optimizeMinSpace;
+ break;
+ case '2':
+ Optimization = optimizeMaxSpeed;
+ break;
+ case 'a':
+ AdditionalOptions += option;
+ break;
+ case 'b':
+ if(third == '0')
+ InlineFunctionExpansion = expandDisable;
+ else if(third == '1')
+ InlineFunctionExpansion = expandOnlyInline;
+ else if(third == '2')
+ InlineFunctionExpansion = expandAnySuitable;
+ else
+ found = false;
+ break;
+ case 'd':
+ Optimization = optimizeDisabled;
+ break;
+ case 'g':
+ GlobalOptimizations = _True;
+ break;
+ case 'i':
+ EnableIntrinsicFunctions = _True;
+ break;
+ case 'p':
+ ImproveFloatingPointConsistency = _True;
+ if(third == '-')
+ ImproveFloatingPointConsistency = _False;
+ break;
+ case 's':
+ FavorSizeOrSpeed = favorSize;
+ break;
+ case 't':
+ FavorSizeOrSpeed = favorSpeed;
+ break;
+ case 'w':
+ AdditionalOptions += option;
+ break;
+ case 'x':
+ Optimization = optimizeFull;
+ break;
+ case 'y':
+ OmitFramePointers = _True;
+ if(third == '-')
+ OmitFramePointers = _False;
+ break;
+ default:
+ found = false; break;
+ }
+ break;
+ case 'P':
+ GeneratePreprocessedFile = preprocessYes;
+ break;
+ case 'Q':
+ if(second == 'I') {
+ AdditionalOptions += option;
+ break;
+ } else if (second == 'R') {
+ QString opt = option + 3;
+ if (opt == "interwork-return") {
+ InterworkCalls = _True;
+ break;
+ } else if (opt == "arch4") {
+ CompileForArchitecture = archArmv4;
+ break;
+ } else if (opt == "arch5") {
+ CompileForArchitecture = archArmv5;
+ break;
+ } else if (opt == "arch4T") {
+ CompileForArchitecture = archArmv4T;
+ break;
+ } else if (opt == "arch5T") {
+ CompileForArchitecture = archArmv5T;
+ break;
+ }
+ } else if (second == 'M') {
+ QString opt = option + 3;
+ if (opt == "mips1") {
+ CompileForArchitecture = archMips1;
+ break;
+ }
+ else if (opt == "mips2") {
+ CompileForArchitecture = archMips2;
+ break;
+ }
+ else if (opt == "mips3") {
+ CompileForArchitecture = archMips3;
+ break;
+ }
+ else if (opt == "mips4") {
+ CompileForArchitecture = archMips4;
+ break;
+ }
+ else if (opt == "mips5") {
+ CompileForArchitecture = archMips5;
+ break;
+ }
+ else if (opt == "mips16") {
+ CompileForArchitecture = archMips16;
+ break;
+ }
+ else if (opt == "mips32") {
+ CompileForArchitecture = archMips32;
+ break;
+ }
+ else if (opt == "mips64") {
+ CompileForArchitecture = archMips64;
+ break;
+ }
+ }
+ found = false; break;
+ case 'R':
+ if(second == 'T' && third == 'C') {
+ if(fourth == '1')
+ BasicRuntimeChecks = runtimeBasicCheckAll;
+ else if(fourth == 'c')
+ SmallerTypeCheck = _True;
+ else if(fourth == 's')
+ BasicRuntimeChecks = runtimeCheckStackFrame;
+ else if(fourth == 'u')
+ BasicRuntimeChecks = runtimeCheckUninitVariables;
+ else
+ found = false; break;
+ }
+ break;
+ case 'T':
+ if(second == 'C') {
+ CompileAs = compileAsC;
+ } else if(second == 'P') {
+ CompileAs = compileAsCPlusPlus;
+ } else {
+ qWarning("Generator: Options '/Tp<filename>' and '/Tc<filename>' are not supported by qmake");
+ found = false; break;
+ }
+ break;
+ case 'U':
+ UndefinePreprocessorDefinitions += option+2;
+ break;
+ case 'V':
+ AdditionalOptions += option;
+ break;
+ case 'W':
+ switch (second) {
+ case 'a':
+ case '4':
+ WarningLevel = warningLevel_4;
+ break;
+ case '3':
+ WarningLevel = warningLevel_3;
+ break;
+ case '2':
+ WarningLevel = warningLevel_2;
+ break;
+ case '1':
+ WarningLevel = warningLevel_1;
+ break;
+ case '0':
+ WarningLevel = warningLevel_0;
+ break;
+ case 'L':
+ AdditionalOptions += option;
+ break;
+ case 'X':
+ WarnAsError = _True;
+ break;
+ case 'p':
+ if(third == '6' && fourth == '4') {
+ if (config->CompilerVersion >= NET2010) {
+ // Deprecated for VS2010 but can be used under Additional Options.
+ AdditionalOptions += option;
+ } else {
+ Detect64BitPortabilityProblems = _True;
+ }
+ break;
+ }
+ // Fallthrough
+ default:
+ found = false; break;
+ }
+ break;
+ case 'X':
+ IgnoreStandardIncludePath = _True;
+ break;
+ case 'Y':
+ switch (second) {
+ case '\0':
+ case '-':
+ AdditionalOptions += option;
+ break;
+ case 'X':
+ UsePrecompiledHeader = pchGenerateAuto;
+ PrecompiledHeaderThrough = option+3;
+ break;
+ case 'c':
+ UsePrecompiledHeader = pchCreateUsingSpecific;
+ PrecompiledHeaderThrough = option+3;
+ break;
+ case 'd':
+ case 'l':
+ AdditionalOptions += option;
+ break;
+ case 'u':
+ UsePrecompiledHeader = pchUseUsingSpecific;
+ PrecompiledHeaderThrough = option+3;
+ break;
+ default:
+ found = false; break;
+ }
+ break;
+ case 'Z':
+ switch (second) {
+ case '7':
+ DebugInformationFormat = debugOldStyleInfo;
+ break;
+ case 'I':
+ DebugInformationFormat = debugEditAndContinue;
+ break;
+ case 'd':
+ DebugInformationFormat = debugLineInfoOnly;
+ break;
+ case 'i':
+ DebugInformationFormat = debugEnabled;
+ break;
+ case 'l':
+ OmitDefaultLibName = _True;
+ break;
+ case 'a':
+ DisableLanguageExtensions = _True;
+ break;
+ case 'e':
+ DisableLanguageExtensions = _False;
+ break;
+ case 'c':
+ if(third == ':') {
+ const char *c = option + 4;
+ // Go to the end of the option
+ while ( *c != '\0' && *c != ' ' && *c != '-')
+ ++c;
+ if(fourth == 'f')
+ ForceConformanceInForLoopScope = ((*c) == '-' ? _False : _True);
+ else if(fourth == 'w')
+ TreatWChar_tAsBuiltInType = ((*c) == '-' ? _False : _True);
+ else
+ found = false;
+ } else {
+ found = false; break;
+ }
+ break;
+ case 'g':
+ case 'm':
+ case 's':
+ AdditionalOptions += option;
+ break;
+ case 'p':
+ switch (third)
+ {
+ case '\0':
+ case '1':
+ StructMemberAlignment = alignSingleByte;
+ if(fourth == '6')
+ StructMemberAlignment = alignSixteenBytes;
+ break;
+ case '2':
+ StructMemberAlignment = alignTwoBytes;
+ break;
+ case '4':
+ StructMemberAlignment = alignFourBytes;
+ break;
+ case '8':
+ StructMemberAlignment = alignEightBytes;
+ break;
+ default:
+ found = false; break;
+ }
+ break;
+ default:
+ found = false; break;
+ }
+ break;
+ case 'a':
+ if (second == 'r' && third == 'c' && fourth == 'h') {
+ if (option[5] == ':') {
+ const char *o = option;
+ if (o[6] == 'S' && o[7] == 'S' && o[8] == 'E') {
+ EnableEnhancedInstructionSet = o[9] == '2' ? archSSE2 : archSSE;
+ break;
+ }
+ }
+ } else if (second == 'n' && third == 'a' && fourth == 'l') {
+ EnablePREfast = _True;
+ break;
+ }
+ found = false;
+ break;
+ case 'b': // see http://msdn2.microsoft.com/en-us/library/ms173499.aspx
+ if (second == 'i' && third == 'g' && fourth == 'o') {
+ const char *o = option;
+ if (o[5] == 'b' && o[6] == 'j') {
+ AdditionalOptions += option;
+ break;
+ }
+ }
+ found = false;
+ break;
+ case 'c':
+ if(second == '\0') {
+ CompileOnly = _True;
+ } else if(second == 'l') {
+ if (config->CompilerVersion < NET2005) {
+ if(*(option+5) == 'n') {
+ CompileAsManaged = managedAssemblyPure;
+ TurnOffAssemblyGeneration = _True;
+ } else if(*(option+5) == 'p') {
+ CompileAsManaged = managedAssemblyPure;
+ warn_msg(WarnLogic, "/clr:pure option only for .NET >= 2005, using /clr");
+ } else if(*(option+5) == 's') {
+ CompileAsManaged = managedAssemblyPure;
+ warn_msg(WarnLogic, "/clr:safe option only for .NET >= 2005, using /clr");
+ } else if(*(option+5) == 'o') {
+ CompileAsManaged = managedAssemblyPure;
+ warn_msg(WarnLogic, "/clr:oldSyntax option only for .NET >= 2005, using /clr");
+ } else if(*(option+5) == 'i') {
+ CompileAsManaged = managedAssemblyPure;
+ warn_msg(WarnLogic, "initialAppDomain enum value unknown, using /crl");
+ } else {
+ CompileAsManaged = managedAssemblyPure;
+ }
+ } else {
+ if(*(option+5) == 'n') {
+ CompileAsManaged = managedAssembly;
+ TurnOffAssemblyGeneration = _True;
+ } else if(*(option+5) == 'p') {
+ CompileAsManaged = managedAssemblyPure;
+ } else if(*(option+5) == 's') {
+ CompileAsManaged = managedAssemblySafe;
+ } else if(*(option+5) == 'o') {
+ CompileAsManaged = managedAssemblyOldSyntax;
+ } else if(*(option+5) == 'i') {
+ CompileAsManaged = managedAssembly;
+ warn_msg(WarnLogic, "initialAppDomain enum value unknown, using /crl default");
+ } else {
+ CompileAsManaged = managedAssembly;
+ }
+ }
+ } else {
+ found = false; break;
+ }
+ break;
+ case 'd':
+ if (second == 'r') {
+ CompileAsManaged = managedAssembly;
+ break;
+ } else if (second != 'o' && third == 'c') {
+ GenerateXMLDocumentationFiles = _True;
+ XMLDocumentationFileName += option+4;
+ break;
+ }
+ found = false;
+ break;
+ case 'e':
+ if (second == 'r' && third == 'r' && fourth == 'o') {
+ if (option[12] == ':') {
+ if ( option[13] == 'n') {
+ ErrorReporting = "None";
+ } else if (option[13] == 'p') {
+ ErrorReporting = "Prompt";
+ } else if (option[13] == 'q') {
+ ErrorReporting = "Queue";
+ } else if (option[13] == 's') {
+ ErrorReporting = "Send";
+ } else {
+ found = false;
+ }
+ break;
+ }
+ }
+ found = false;
+ break;
+ case 'f':
+ if(second == 'p' && third == ':') {
+ // Go to the end of the option
+ const char *c = option + 4;
+ while (*c != '\0' && *c != ' ' && *c != '-')
+ ++c;
+ switch (fourth) {
+ case 'e':
+ FloatingPointExceptions = ((*c) == '-' ? _False : _True);
+ break;
+ case 'f':
+ FloatingPointModel = floatingPointFast;
+ break;
+ case 'p':
+ FloatingPointModel = floatingPointPrecise;
+ break;
+ case 's':
+ FloatingPointModel = floatingPointStrict;
+ break;
+ default:
+ found = false;
+ break;
+ }
+ }
+ break;
+ case 'n':
+ if(second == 'o' && third == 'B' && fourth == 'o') {
+ AdditionalOptions += "/noBool";
+ break;
+ }
+ if(second == 'o' && third == 'l' && fourth == 'o') {
+ SuppressStartupBanner = _True;
+ break;
+ }
+ found = false; break;
+ case 'o':
+ if (second == 'p' && third == 'e' && fourth == 'n') {
+ OpenMP = _True;
+ break;
+ }
+ found = false; break;
+ case 's':
+ if(second == 'h' && third == 'o' && fourth == 'w') {
+ ShowIncludes = _True;
+ break;
+ }
+ found = false; break;
+ case 'u':
+ UndefineAllPreprocessorDefinitions = _True;
+ break;
+ case 'v':
+ if(second == 'd' || second == 'm') {
+ AdditionalOptions += option;
+ break;
+ }
+ found = false; break;
+ case 'w':
+ switch (second) {
+ case '\0':
+ WarningLevel = warningLevel_0;
+ break;
+ case 'd':
+ DisableSpecificWarnings += option+3;
+ break;
+ default:
+ AdditionalOptions += option;
+ }
+ break;
+ default:
+ AdditionalOptions += option;
+ break;
+ }
+ if(!found) {
+ warn_msg(WarnLogic, "Could not parse Compiler option: %s, added as AdditionalOption", option);
+ AdditionalOptions += option;
+ }
+ return true;
+}
+
+// VCLinkerTool -----------------------------------------------------
+VCLinkerTool::VCLinkerTool()
+ : DataExecutionPrevention(unset),
+ EnableCOMDATFolding(optFoldingDefault),
+ GenerateDebugInformation(unset),
+ GenerateMapFile(unset),
+ HeapCommitSize(-1),
+ HeapReserveSize(-1),
+ IgnoreAllDefaultLibraries(unset),
+ IgnoreEmbeddedIDL(unset),
+ IgnoreImportLibrary(_True),
+ LargeAddressAware(addrAwareDefault),
+ LinkDLL(unset),
+ LinkIncremental(linkIncrementalDefault),
+ LinkTimeCodeGeneration(optLTCGDefault),
+ MapExports(unset),
+ MapLines(unset),
+ OptimizeForWindows98(optWin98Default),
+ OptimizeReferences(optReferencesDefault),
+ RandomizedBaseAddress(unset),
+ RegisterOutput(unset),
+ ResourceOnlyDLL(unset),
+ SetChecksum(unset),
+ ShowProgress(linkProgressNotSet),
+ StackCommitSize(-1),
+ StackReserveSize(-1),
+ SubSystem(subSystemNotSet),
+ SupportUnloadOfDelayLoadedDLL(unset),
+ SuppressStartupBanner(unset),
+ SwapRunFromCD(unset),
+ SwapRunFromNet(unset),
+ TargetMachine(machineNotSet),
+ TerminalServerAware(termSvrAwareDefault),
+ TreatWarningsAsErrors(unset),
+ TurnOffAssemblyGeneration(unset),
+ TypeLibraryResourceID(0),
+ GenerateManifest(unset),
+ EnableUAC(unset),
+ UACUIAccess(unset),
+ SectionAlignment(-1),
+ PreventDllBinding(unset),
+ AllowIsolation(unset),
+ AssemblyDebug(unset),
+ CLRUnmanagedCodeCheck(unset),
+ DelaySign(unset)
+{
+}
+
+// Hashing routine to do fast option lookups ----
+// Slightly rewritten to stop on ':' ',' and '\0'
+// Original routine in qtranslator.cpp ----------
+static uint elfHash(const char* name)
+{
+ const uchar *k;
+ uint h = 0;
+ uint g;
+
+ if(name) {
+ k = (const uchar *) name;
+ while((*k) &&
+ (*k)!= ':' &&
+ (*k)!=',' &&
+ (*k)!=' ') {
+ h = (h << 4) + *k++;
+ if((g = (h & 0xf0000000)) != 0)
+ h ^= g >> 24;
+ h &= ~g;
+ }
+ }
+ if(!h)
+ h = 1;
+ return h;
+}
+
+//#define USE_DISPLAY_HASH
+#ifdef USE_DISPLAY_HASH
+static void displayHash(const char* str)
+{
+ printf("case 0x%07x: // %s\n break;\n", elfHash(str), str);
+}
+#endif
+
+bool VCLinkerTool::parseOption(const char* option)
+{
+#ifdef USE_DISPLAY_HASH
+ // Main options
+ displayHash("/ALIGN"); displayHash("/ALLOWBIND"); displayHash("/ASSEMBLYMODULE");
+ displayHash("/ASSEMBLYRESOURCE"); displayHash("/BASE"); displayHash("/DEBUG");
+ displayHash("/DEF"); displayHash("/DEFAULTLIB"); displayHash("/DELAY");
+ displayHash("/DELAYLOAD"); displayHash("/DLL"); displayHash("/DRIVER");
+ displayHash("/ENTRY"); displayHash("/EXETYPE"); displayHash("/EXPORT");
+ displayHash("/FIXED"); displayHash("/FORCE"); displayHash("/HEAP");
+ displayHash("/IDLOUT"); displayHash("/IGNORE"); displayHash("/IGNOREIDL"); displayHash("/IMPLIB");
+ displayHash("/INCLUDE"); displayHash("/INCREMENTAL"); displayHash("/LARGEADDRESSAWARE");
+ displayHash("/LIBPATH"); displayHash("/LTCG"); displayHash("/MACHINE");
+ displayHash("/MAP"); displayHash("/MAPINFO"); displayHash("/MERGE");
+ displayHash("/MIDL"); displayHash("/NOASSEMBLY"); displayHash("/NODEFAULTLIB");
+ displayHash("/NOENTRY"); displayHash("/NOLOGO"); displayHash("/OPT");
+ displayHash("/ORDER"); displayHash("/OUT"); displayHash("/PDB");
+ displayHash("/PDBSTRIPPED"); displayHash("/RELEASE"); displayHash("/SECTION");
+ displayHash("/STACK"); displayHash("/STUB"); displayHash("/SUBSYSTEM");
+ displayHash("/SWAPRUN"); displayHash("/TLBID"); displayHash("/TLBOUT");
+ displayHash("/TSAWARE"); displayHash("/VERBOSE"); displayHash("/VERSION");
+ displayHash("/VXD"); displayHash("/WS "); displayHash("/libpath");
+
+#endif
+#ifdef USE_DISPLAY_HASH
+ // Sub options
+ displayHash("UNLOAD"); displayHash("NOBIND"); displayHash("no"); displayHash("NOSTATUS"); displayHash("STATUS");
+ displayHash("AM33"); displayHash("ARM"); displayHash("CEE"); displayHash("EBC"); displayHash("IA64"); displayHash("X86"); displayHash("X64"); displayHash("M32R");
+ displayHash("MIPS"); displayHash("MIPS16"); displayHash("MIPSFPU"); displayHash("MIPSFPU16"); displayHash("MIPSR41XX"); displayHash("PPC");
+ displayHash("SH3"); displayHash("SH3DSP"); displayHash("SH4"); displayHash("SH5"); displayHash("THUMB"); displayHash("TRICORE"); displayHash("EXPORTS");
+ displayHash("LINES"); displayHash("REF"); displayHash("NOREF"); displayHash("ICF"); displayHash("WIN98"); displayHash("NOWIN98");
+ displayHash("CONSOLE"); displayHash("EFI_APPLICATION"); displayHash("EFI_BOOT_SERVICE_DRIVER"); displayHash("EFI_ROM"); displayHash("EFI_RUNTIME_DRIVER"); displayHash("NATIVE");
+ displayHash("POSIX"); displayHash("WINDOWS"); displayHash("WINDOWSCE"); displayHash("NET"); displayHash("CD"); displayHash("NO");
+#endif
+ bool found = true;
+ const uint optionHash = elfHash(option);
+ if (config->CompilerVersion < NET2010) {
+ switch (optionHash) {
+ case 0x3360dbe: // /ALIGN[:number]
+ case 0x1485c34: // /ALLOWBIND[:NO]
+ case 0x33aec94: // /FIXED[:NO]
+ case 0x7988f7e: // /SECTION:name,[E][R][W][S][D][K][L][P][X][,ALIGN=#]
+ case 0x0348992: // /STUB:filename
+ AdditionalOptions += option;
+ return true;
+ }
+ }
+
+ switch (optionHash) {
+ case 0x6b21972: // /DEFAULTLIB:library
+ case 0x396ea92: // /DRIVER[:UPONLY | :WDM]
+ case 0xaca9d75: // /EXETYPE[:DYNAMIC | :DEV386]
+ case 0x3ad5444: // /EXPORT:entryname[,@ordinal[,NONAME]][,DATA]
+ case 0x33b4675: // /FORCE:[MULTIPLE|UNRESOLVED]
+ case 0x3dc3455: // /IGNORE:number,number,number,number ### NOTE: This one is undocumented, but it is even used by Microsoft.
+ // In recent versions of the Microsoft linker they have disabled this undocumented feature.
+ case 0x0034bc4: // /VXD
+ AdditionalOptions += option;
+ break;
+ case 0x3360dbe: // /ALIGN[:number]
+ SectionAlignment = QString(option+7).toLongLong();
+ break;
+ case 0x1485c34: // /ALLOWBIND[:NO]
+ if(*(option+10) == ':' && (*(option+11) == 'n' || *(option+11) == 'N'))
+ PreventDllBinding = _False;
+ else
+ PreventDllBinding = _True;
+ break;
+ case 0x312011e: // /ALLOWISOLATION[:NO]
+ if(*(option+15) == ':' && (*(option+16) == 'n' || *(option+16) == 'N'))
+ AllowIsolation = _False;
+ else
+ AllowIsolation = _True;
+ break;
+ case 0x679c075: // /ASSEMBLYMODULE:filename
+ AddModuleNamesToAssembly += option+15;
+ break;
+ case 0x75f35f7: // /ASSEMBLYDEBUG[:DISABLE]
+ if(*(option+14) == ':' && (*(option+15) == 'D'))
+ AssemblyDebug = _False;
+ else
+ AssemblyDebug = _True;
+ break;
+ case 0x43294a5: // /ASSEMBLYLINKRESOURCE:filename
+ AssemblyLinkResource += option+22;
+ break;
+ case 0x062d065: // /ASSEMBLYRESOURCE:filename
+ LinkToManagedResourceFile = option+18;
+ break;
+ case 0x0336675: // /BASE:{address | @filename,key}
+ // Do we need to do a manual lookup when '@filename,key'?
+ // Seems BaseAddress only can contain the location...
+ // We don't use it in Qt, so keep it simple for now
+ BaseAddress = option+6;
+ break;
+ case 0x63bf065: // /CLRIMAGETYPE:{IJW|PURE|SAFE}
+ if(*(option+14) == 'I')
+ CLRImageType = "ForceIJWImage";
+ else if(*(option+14) == 'P')
+ CLRImageType = "ForcePureILImage";
+ else if(*(option+14) == 'S')
+ CLRImageType = "ForceSafeILImage";
+ break;
+ case 0x5f2a6a2: // /CLRSUPPORTLASTERROR{:NO | SYSTEMDLL}
+ if(*(option+20) == ':') {
+ if(*(option+21) == 'N') {
+ CLRSupportLastError = "Disabled";
+ } else if(*(option+21) == 'S') {
+ CLRSupportLastError = "SystemDlls";
+ }
+ } else {
+ CLRSupportLastError = "Enabled";
+ }
+ break;
+ case 0xc7984f5: // /CLRTHREADATTRIBUTE:{STA|MTA|NONE}
+ if(*(option+20) == 'N')
+ CLRThreadAttribute = "DefaultThreadingAttribute";
+ else if(*(option+20) == 'M')
+ CLRThreadAttribute = "MTAThreadingAttribute";
+ else if(*(option+20) == 'S')
+ CLRThreadAttribute = "STAThreadingAttribute";
+ break;
+ case 0xa8c637b: // /CLRUNMANAGEDCODECHECK[:NO]
+ if(*(option+23) == 'N')
+ CLRUnmanagedCodeCheck = _False;
+ else
+ CLRUnmanagedCodeCheck = _True;
+ break;
+ case 0x62d9e94: // /MANIFEST[:NO]
+ if ((*(option+9) == ':' && (*(option+10) == 'N' || *(option+10) == 'n')))
+ GenerateManifest = _False;
+ else
+ GenerateManifest = _True;
+ break;
+ case 0x8b64559: // /MANIFESTDEPENDENCY:manifest_dependency
+ AdditionalManifestDependencies += option+20;
+ break;
+ case 0xe9e8195: // /MANIFESTFILE:filename
+ ManifestFile = option+14;
+ break;
+ case 0x9e9fb83: // /MANIFESTUAC http://msdn.microsoft.com/en-us/library/bb384691%28VS.100%29.aspx
+ if ((*(option+12) == ':' && (*(option+13) == 'N' || *(option+13) == 'n')))
+ EnableUAC = _False;
+ else if((*(option+12) == ':' && (*(option+13) == 'l' || *(option+14) == 'e'))) { // level
+ if(*(option+20) == 'a')
+ UACExecutionLevel = "AsInvoker";
+ else if(*(option+20) == 'h')
+ UACExecutionLevel = "HighestAvailable";
+ else if(*(option+20) == 'r')
+ UACExecutionLevel = "RequireAdministrator";
+ } else if((*(option+12) == ':' && (*(option+13) == 'u' || *(option+14) == 'i'))) { // uiAccess
+ if(*(option+22) == 't')
+ UACUIAccess = _True;
+ else
+ UACUIAccess = _False;
+ } else if((*(option+12) == ':' && (*(option+13) == 'f' || *(option+14) == 'r'))) { // fragment
+ AdditionalOptions += option;
+ }else
+ EnableUAC = _True;
+ break;
+ case 0x3389797: // /DEBUG
+ GenerateDebugInformation = _True;
+ break;
+ case 0x0033896: // /DEF:filename
+ ModuleDefinitionFile = option+5;
+ break;
+ case 0x338a069: // /DELAY:{UNLOAD | NOBIND}
+ // MS documentation does not specify what to do with
+ // this option, so we'll put it in AdditionalOptions
+ AdditionalOptions += option;
+ break;
+ case 0x06f4bf4: // /DELAYLOAD:dllname
+ DelayLoadDLLs += option+11;
+ break;
+ case 0x06d451e: // /DELAYSIGN[:NO]
+ if(*(option+10) == ':' && (*(option+11) == 'n' || *(option+11) == 'N'))
+ DelaySign = _False;
+ else
+ DelaySign = _True;
+ break;
+ case 0x003390c: // /DLL
+ // This option is not used for vcproj files
+ break;
+ case 0x2ee8415: // /DYNAMICBASE[:NO]
+ if(*(option+12) == ':' && (*(option+13) == 'n' || *(option+13) == 'N'))
+ RandomizedBaseAddress = _False;
+ else
+ RandomizedBaseAddress = _True;
+ break;
+ case 0x33a3979: // /ENTRY:function
+ EntryPointSymbol = option+7;
+ break;
+ case 0x4504334: // /ERRORREPORT:[ NONE | PROMPT | QUEUE | SEND ]
+ if(*(option+12) == ':' ) {
+ if(*(option+13) == 'N')
+ LinkErrorReporting = "NoErrorReport";
+ else if(*(option+13) == 'P')
+ LinkErrorReporting = "PromptImmediately";
+ else if(*(option+13) == 'Q')
+ LinkErrorReporting = "QueueForNextLogin";
+ else if(*(option+13) == 'S')
+ LinkErrorReporting = "SendErrorReport";
+ }
+ break;
+ case 0x033c960: // /HEAP:reserve[,commit]
+ {
+ QStringList both = QString(option+6).split(",");
+ HeapReserveSize = both[0].toLongLong();
+ if(both.count() == 2)
+ HeapCommitSize = both[1].toLongLong();
+ }
+ break;
+ case 0x3d91494: // /IDLOUT:[path\]filename
+ MergedIDLBaseFileName = option+8;
+ break;
+ case 0x345a04c: // /IGNOREIDL
+ IgnoreEmbeddedIDL = _True;
+ break;
+ case 0x3e250e2: // /IMPLIB:filename
+ ImportLibrary = option+8;
+ break;
+ case 0xe281ab5: // /INCLUDE:symbol
+ ForceSymbolReferences += option+9;
+ break;
+ case 0xb28103c: // /INCREMENTAL[:no]
+ if(*(option+12) == ':' &&
+ (*(option+13) == 'n' || *(option+13) == 'N'))
+ LinkIncremental = linkIncrementalNo;
+ else
+ LinkIncremental = linkIncrementalYes;
+ break;
+ case 0x07f1ab2: // /KEYCONTAINER:name
+ KeyContainer = option+14;
+ break;
+ case 0xfadaf35: // /KEYFILE:filename
+ KeyFile = option+9;
+ break;
+ case 0x26e4675: // /LARGEADDRESSAWARE[:no]
+ if(*(option+18) == ':' &&
+ *(option+19) == 'n')
+ LargeAddressAware = addrAwareNoLarge;
+ else
+ LargeAddressAware = addrAwareLarge;
+ break;
+ case 0x2f96bc8: // /libpath:dir
+ case 0x0d745c8: // /LIBPATH:dir
+ AdditionalLibraryDirectories += option+9;
+ break;
+ case 0x0341877: // /LTCG[:NOSTATUS|:STATUS]
+ config->WholeProgramOptimization = _True;
+ if (config->CompilerVersion >= NET2005) {
+ LinkTimeCodeGeneration = optLTCGEnabled;
+ if(*(option+5) == ':') {
+ const char* str = option+6;
+ if (*str == 'S')
+ ShowProgress = linkProgressAll;
+#ifndef Q_OS_WIN
+ else if (strncasecmp(str, "pginstrument", 12))
+ LinkTimeCodeGeneration = optLTCGInstrument;
+ else if (strncasecmp(str, "pgoptimize", 10))
+ LinkTimeCodeGeneration = optLTCGOptimize;
+ else if (strncasecmp(str, "pgupdate", 8 ))
+ LinkTimeCodeGeneration = optLTCGUpdate;
+#else
+ else if (_stricmp(str, "pginstrument"))
+ LinkTimeCodeGeneration = optLTCGInstrument;
+ else if (_stricmp(str, "pgoptimize"))
+ LinkTimeCodeGeneration = optLTCGOptimize;
+ else if (_stricmp(str, "pgupdate"))
+ LinkTimeCodeGeneration = optLTCGUpdate;
+#endif
+ }
+ } else {
+ AdditionalOptions.append(option);
+ }
+ break;
+ case 0x379ED25:
+ case 0x157cf65: // /MACHINE:{AM33|ARM|CEE|IA64|X86|M32R|MIPS|MIPS16|MIPSFPU|MIPSFPU16|MIPSR41XX|PPC|SH3|SH4|SH5|THUMB|TRICORE}
+ switch (elfHash(option+9)) {
+ // Very limited documentation on all options but X86,
+ case 0x0005bb6: // X86
+ TargetMachine = machineX86;
+ break;
+ case 0x0005b94: // X64
+ TargetMachine = machineX64;
+ break;
+ // so we put the others in AdditionalOptions...
+ case 0x0046063: // AM33
+ case 0x000466d: // ARM
+ case 0x0004795: // CEE
+ case 0x0004963: // EBC
+ case 0x004d494: // IA64
+ case 0x0050672: // M32R
+ case 0x0051e53: // MIPS
+ case 0x51e5646: // MIPS16
+ case 0x1e57b05: // MIPSFPU
+ case 0x57b09a6: // MIPSFPU16
+ case 0x5852738: // MIPSR41XX
+ case 0x0005543: // PPC
+ case 0x00057b3: // SH3
+ case 0x57b7980: // SH3DSP
+ case 0x00057b4: // SH4
+ case 0x00057b5: // SH5
+ case 0x058da12: // THUMB
+ case 0x96d8435: // TRICORE
+ default:
+ AdditionalOptions += option;
+ break;
+ }
+ break;
+ case 0x0034160: // /MAP[:filename]
+ GenerateMapFile = _True;
+ if (option[4] == ':')
+ MapFileName = option+5;
+ break;
+ case 0x164e1ef: // /MAPINFO:{EXPORTS|LINES}
+ if(*(option+9) == 'E')
+ MapExports = _True;
+ else if(*(option+9) == 'L')
+ MapLines = _True;
+ break;
+ case 0x341a6b5: // /MERGE:from=to
+ MergeSections = option+7;
+ break;
+ case 0x0341d8c: // /MIDL:@file
+ MidlCommandFile = option+7;
+ break;
+ case 0x84e2679: // /NOASSEMBLY
+ TurnOffAssemblyGeneration = _True;
+ break;
+ case 0x2b21942: // /NODEFAULTLIB[:library]
+ if(*(option+13) == '\0')
+ IgnoreAllDefaultLibraries = _True;
+ else
+ IgnoreDefaultLibraryNames += option+14;
+ break;
+ case 0x33a3a39: // /NOENTRY
+ ResourceOnlyDLL = _True;
+ break;
+ case 0x434138f: // /NOLOGO
+ SuppressStartupBanner = _True;
+ break;
+ case 0xc841054: // /NXCOMPAT[:NO]
+ if ((*(option+9) == ':' && (*(option+10) == 'N' || *(option+10) == 'n')))
+ DataExecutionPrevention = _False;
+ else
+ DataExecutionPrevention = _True;
+ break;
+ case 0x0034454: // /OPT:{REF | NOREF | ICF[=iterations] | NOICF | WIN98 | NOWIN98}
+ {
+ char third = *(option+7);
+ switch (third) {
+ case 'F': // REF
+ if(*(option+5) == 'R') {
+ OptimizeReferences = optReferences;
+ } else { // ICF[=iterations]
+ EnableCOMDATFolding = optFolding;
+ // [=iterations] case is not documented
+ }
+ break;
+ case 'R': // NOREF
+ OptimizeReferences = optNoReferences;
+ break;
+ case 'I': // NOICF
+ EnableCOMDATFolding = optNoFolding;
+ break;
+ case 'N': // WIN98
+ OptimizeForWindows98 = optWin98Yes;
+ break;
+ case 'W': // NOWIN98
+ OptimizeForWindows98 = optWin98No;
+ break;
+ default:
+ found = false;
+ }
+ }
+ break;
+ case 0x34468a2: // /ORDER:@filename
+ FunctionOrder = option+8;
+ break;
+ case 0x00344a4: // /OUT:filename
+ OutputFile = option+5;
+ break;
+ case 0x0034482: // /PDB:filename
+ ProgramDatabaseFile = option+5;
+ break;
+ case 0xa2ad314: // /PDBSTRIPPED:pdb_file_name
+ StripPrivateSymbols = option+13;
+ break;
+ case 0x6a09535: // /RELEASE
+ SetChecksum = _True;
+ break;
+ case 0x348857b: // /STACK:reserve[,commit]
+ {
+ QStringList both = QString(option+7).split(",");
+ StackReserveSize = both[0].toLongLong();
+ if(both.count() == 2)
+ StackCommitSize = both[1].toLongLong();
+ }
+ break;
+ case 0x75AA4D8: // /SAFESH:{NO}
+ {
+ AdditionalOptions += option;
+ break;
+ }
+ case 0x9B3C00D:
+ case 0x78dc00d: // /SUBSYSTEM:{CONSOLE|EFI_APPLICATION|EFI_BOOT_SERVICE_DRIVER|EFI_ROM|EFI_RUNTIME_DRIVER|NATIVE|POSIX|WINDOWS|WINDOWSCE}[,major[.minor]]
+ {
+ // Split up in subsystem, and version number
+ QStringList both = QString(option+11).split(",");
+ switch (elfHash(both[0].toLatin1())) {
+ case 0x8438445: // CONSOLE
+ SubSystem = subSystemConsole;
+ break;
+ case 0xbe29493: // WINDOWS
+ SubSystem = subSystemWindows;
+ break;
+ // The following are undocumented, so add them to AdditionalOptions
+ case 0x240949e: // EFI_APPLICATION
+ case 0xe617652: // EFI_BOOT_SERVICE_DRIVER
+ case 0x9af477d: // EFI_ROM
+ case 0xd34df42: // EFI_RUNTIME_DRIVER
+ case 0x5268ea5: // NATIVE
+ case 0x05547e8: // POSIX
+ case 0x2949c95: // WINDOWSCE
+ case 0x4B69795: // windowsce
+ AdditionalOptions += option;
+ break;
+ default:
+ found = false;
+ }
+ }
+ break;
+ case 0x8b654de: // /SWAPRUN:{NET | CD}
+ if(*(option+9) == 'N')
+ SwapRunFromNet = _True;
+ else if(*(option+9) == 'C')
+ SwapRunFromCD = _True;
+ else
+ found = false;
+ break;
+ case 0x34906d4: // /TLBID:id
+ TypeLibraryResourceID = QString(option+7).toLongLong();
+ break;
+ case 0x4907494: // /TLBOUT:[path\]filename
+ TypeLibraryFile = option+8;
+ break;
+ case 0x976b525: // /TSAWARE[:NO]
+ if(*(option+8) == ':')
+ TerminalServerAware = termSvrAwareNo;
+ else
+ TerminalServerAware = termSvrAwareYes;
+ break;
+ case 0xaa67735: // /VERBOSE[:lib]
+ if(*(option+9) == ':') {
+ ShowProgress = linkProgressLibs;
+ AdditionalOptions += option;
+ } else {
+ ShowProgress = linkProgressAll;
+ }
+ break;
+ case 0xaa77f7e: // /VERSION:major[.minor]
+ Version = option+9;
+ break;
+ case 0x0034c50: // /WS[:NO]
+ if (config->CompilerVersion >= NET2010) {
+ if(*(option+3) == ':')
+ TreatWarningsAsErrors = _False;
+ else
+ TreatWarningsAsErrors = _True;
+ } else {
+ AdditionalOptions += option;
+ }
+ break;
+ default:
+ AdditionalOptions += option;
+ break;
+ }
+ if(!found) {
+ warn_msg(WarnLogic, "Could not parse Linker options: %s, added as AdditionalOption", option);
+ AdditionalOptions += option;
+ }
+ return found;
+}
+
+// VCMIDLTool -------------------------------------------------------
+VCMIDLTool::VCMIDLTool()
+ : DefaultCharType(midlCharUnsigned),
+ EnableErrorChecks(midlDisableAll),
+ ErrorCheckAllocations(unset),
+ ErrorCheckBounds(unset),
+ ErrorCheckEnumRange(unset),
+ ErrorCheckRefPointers(unset),
+ ErrorCheckStubData(unset),
+ GenerateStublessProxies(unset),
+ GenerateTypeLibrary(unset),
+ IgnoreStandardIncludePath(unset),
+ MkTypLibCompatible(unset),
+ StructMemberAlignment(midlAlignNotSet),
+ SuppressStartupBanner(unset),
+ TargetEnvironment(midlTargetNotSet),
+ ValidateParameters(unset),
+ WarnAsError(unset),
+ WarningLevel(midlWarningLevel_0),
+ ApplicationConfigurationMode(unset),
+ ValidateAllParameters(unset),
+ SuppressCompilerWarnings(unset),
+ LocaleID(-1)
+{
+}
+
+bool VCMIDLTool::parseOption(const char* option)
+{
+#ifdef USE_DISPLAY_HASH
+ displayHash("/D name[=def]"); displayHash("/I directory-list"); displayHash("/Oi");
+ displayHash("/Oic"); displayHash("/Oicf"); displayHash("/Oif"); displayHash("/Os");
+ displayHash("/U name"); displayHash("/WX"); displayHash("/W{0|1|2|3|4}");
+ displayHash("/Zp {N}"); displayHash("/Zs"); displayHash("/acf filename");
+ displayHash("/align {N}"); displayHash("/app_config"); displayHash("/c_ext");
+ displayHash("/char ascii7"); displayHash("/char signed"); displayHash("/char unsigned");
+ displayHash("/client none"); displayHash("/client stub"); displayHash("/confirm");
+ displayHash("/cpp_cmd cmd_line"); displayHash("/cpp_opt options");
+ displayHash("/cstub filename"); displayHash("/dlldata filename"); displayHash("/env win32");
+ displayHash("/env win64"); displayHash("/error all"); displayHash("/error allocation");
+ displayHash("/error bounds_check"); displayHash("/error enum"); displayHash("/error none");
+ displayHash("/error ref"); displayHash("/error stub_data"); displayHash("/h filename");
+ displayHash("/header filename"); displayHash("/iid filename"); displayHash("/lcid");
+ displayHash("/mktyplib203"); displayHash("/ms_ext"); displayHash("/ms_union");
+ displayHash("/msc_ver <nnnn>"); displayHash("/newtlb"); displayHash("/no_cpp");
+ displayHash("/no_def_idir"); displayHash("/no_default_epv"); displayHash("/no_format_opt");
+ displayHash("/no_warn"); displayHash("/nocpp"); displayHash("/nologo"); displayHash("/notlb");
+ displayHash("/o filename"); displayHash("/oldnames"); displayHash("/oldtlb");
+ displayHash("/osf"); displayHash("/out directory"); displayHash("/pack {N}");
+ displayHash("/prefix all"); displayHash("/prefix client"); displayHash("/prefix server");
+ displayHash("/prefix switch"); displayHash("/protocol all"); displayHash("/protocol dce");
+ displayHash("/protocol ndr64"); displayHash("/proxy filename"); displayHash("/robust");
+ displayHash("/rpcss"); displayHash("/savePP"); displayHash("/server none");
+ displayHash("/server stub"); displayHash("/sstub filename"); displayHash("/syntax_check");
+ displayHash("/target {system}"); displayHash("/tlb filename"); displayHash("/use_epv");
+ displayHash("/win32"); displayHash("/win64");
+#endif
+ bool found = true;
+ int offset = 0;
+
+ const uint optionHash = elfHash(option);
+
+ if (config->CompilerVersion < NET2010) {
+ switch (optionHash) {
+ case 0x5b1cb97: // /app_config
+ case 0x5a2fc64: // /client {none|stub}
+ case 0x35aabb2: // /cstub filename
+ case 0x64ceb12: // /newtlb
+ case 0x556dbee: // /no_warn
+ case 0x662bb12: // /oldtlb
+ case 0x69c9cf2: // /server {none|stub}
+ case 0x36aabb2: // /sstub filename
+ AdditionalOptions += option;
+ return true;
+ }
+ }
+
+ switch(optionHash) {
+ case 0x0000334: // /D name[=def]
+ PreprocessorDefinitions += option+3;
+ break;
+ case 0x0000339: // /I directory-list
+ AdditionalIncludeDirectories += option+3;
+ break;
+ case 0x0345f96: // /Oicf
+ case 0x00345f6: // /Oif
+ GenerateStublessProxies = _True;
+ break;
+ case 0x0000345: // /U name
+ UndefinePreprocessorDefinitions += option+3;
+ break;
+ case 0x00034c8: // /WX
+ WarnAsError = _True;
+ break;
+ case 0x3582fde: // /align {N}
+ offset = 3; // Fallthrough
+ case 0x0003510: // /Zp {N}
+ switch (*(option+offset+4)) {
+ case '1':
+ StructMemberAlignment = (*(option+offset+5) == '\0') ? midlAlignSingleByte : midlAlignSixteenBytes;
+ break;
+ case '2':
+ StructMemberAlignment = midlAlignTwoBytes;
+ break;
+ case '4':
+ StructMemberAlignment = midlAlignFourBytes;
+ break;
+ case '8':
+ StructMemberAlignment = midlAlignEightBytes;
+ break;
+ default:
+ found = false;
+ }
+ break;
+ case 0x5b1cb97: // /app_config
+ ApplicationConfigurationMode = _True;
+ break;
+ case 0x0359e82: // /char {ascii7|signed|unsigned}
+ switch(*(option+6)) {
+ case 'a':
+ DefaultCharType = midlCharAscii7;
+ break;
+ case 's':
+ DefaultCharType = midlCharSigned;
+ break;
+ case 'u':
+ DefaultCharType = midlCharUnsigned;
+ break;
+ default:
+ found = false;
+ }
+ break;
+ case 0x5a2fc64: // /client {none|stub}
+ if(*(option+8) == 's')
+ GenerateClientFiles = "Stub";
+ else
+ GenerateClientFiles = "None";
+ break;
+ case 0xa766524: // /cpp_opt options
+ CPreprocessOptions += option+9;
+ break;
+ case 0x35aabb2: // /cstub filename
+ ClientStubFile = option+7;
+ break;
+ case 0xb32abf1: // /dlldata filename
+ DLLDataFileName = option + 9;
+ break;
+ case 0x0035c56: // /env {win32|win64}
+ TargetEnvironment = (*(option+8) == '6') ? midlTargetWin64 : midlTargetWin32;
+ break;
+ case 0x35c9962: // /error {all|allocation|bounds_check|enum|none|ref|stub_data}
+ EnableErrorChecks = midlEnableCustom;
+ switch (*(option+7)) {
+ case 'a':
+ if(*(option+10) == '\0')
+ EnableErrorChecks = midlEnableAll;
+ else
+ ErrorCheckAllocations = _True;
+ break;
+ case 'b':
+ ErrorCheckBounds = _True;
+ break;
+ case 'e':
+ ErrorCheckEnumRange = _True;
+ break;
+ case 'n':
+ EnableErrorChecks = midlDisableAll;
+ break;
+ case 'r':
+ ErrorCheckRefPointers = _True;
+ break;
+ case 's':
+ ErrorCheckStubData = _True;
+ break;
+ default:
+ found = false;
+ }
+ break;
+ case 0x5eb7af2: // /header filename
+ offset = 5;
+ case 0x0000358: // /h filename
+ HeaderFileName = option + offset + 3;
+ break;
+ case 0x0035ff4: // /iid filename
+ InterfaceIdentifierFileName = option+5;
+ break;
+ case 0x64b7933: // /mktyplib203
+ MkTypLibCompatible = _True;
+ break;
+ case 0x64ceb12: // /newtlb
+ TypeLibFormat = "NewFormat";
+ break;
+ case 0x8e0b0a2: // /no_def_idir
+ IgnoreStandardIncludePath = _True;
+ break;
+ case 0x65635ef: // /nologo
+ SuppressStartupBanner = _True;
+ break;
+ case 0x695e9f4: // /no_robust
+ ValidateAllParameters = _False;
+ break;
+ case 0x3656b22: // /notlb
+ GenerateTypeLibrary = _True;
+ break;
+ case 0x556dbee: // /no_warn
+ SuppressCompilerWarnings = _True;
+ break;
+ case 0x000035f: // /o filename
+ RedirectOutputAndErrors = option+3;
+ break;
+ case 0x662bb12: // /oldtlb
+ TypeLibFormat = "OldFormat";
+ break;
+ case 0x00366c4: // /out directory
+ OutputDirectory = option+5;
+ break;
+ case 0x36796f9: // /proxy filename
+ ProxyFileName = option+7;
+ break;
+ case 0x6959c94: // /robust
+ ValidateParameters = _True;
+ break;
+ case 0x6a88df4: // /target {system}
+ if(*(option+11) == '6')
+ TargetEnvironment = midlTargetWin64;
+ else
+ TargetEnvironment = midlTargetWin32;
+ break;
+ case 0x69c9cf2: // /server {none|stub}
+ if(*(option+8) == 's')
+ GenerateServerFiles = "Stub";
+ else
+ GenerateServerFiles = "None";
+ break;
+ case 0x36aabb2: // /sstub filename
+ ServerStubFile = option+7;
+ break;
+ case 0x0036b22: // /tlb filename
+ TypeLibraryName = option+5;
+ break;
+ case 0x36e0162: // /win32
+ TargetEnvironment = midlTargetWin32;
+ break;
+ case 0x36e0194: // /win64
+ TargetEnvironment = midlTargetWin64;
+ break;
+ case 0x0003459: // /Oi
+ case 0x00345f3: // /Oic
+ case 0x0003463: // /Os
+ case 0x0003513: // /Zs
+ case 0x0035796: // /acf filename
+ case 0x3595cf4: // /c_ext
+ case 0xa64d3dd: // /confirm
+ case 0xa765b64: // /cpp_cmd cmd_line
+ case 0x03629f4: // /lcid
+ case 0x6495cc4: // /ms_ext
+ case 0x96c7a1e: // /ms_union
+ case 0x4996fa2: // /msc_ver <nnnn>
+ case 0x6555a40: // /no_cpp
+ case 0xf64d6a6: // /no_default_epv
+ case 0x6dd9384: // /no_format_opt
+ case 0x3655a70: // /nocpp
+ case 0x2b455a3: // /oldnames
+ case 0x0036696: // /osf
+ case 0x036679b: // /pack {N}
+ case 0x678bd38: // /prefix {all|client|server|switch}
+ case 0x96b702c: // /protocol {all|dce|ndr64}
+ case 0x3696aa3: // /rpcss
+ case 0x698ca60: // /savePP
+ case 0xce9b12b: // /syntax_check
+ case 0xc9b5f16: // /use_epv
+ AdditionalOptions += option;
+ break;
+ default:
+ // /W{0|1|2|3|4} case
+ if(*(option+1) == 'W') {
+ switch (*(option+2)) {
+ case '0':
+ WarningLevel = midlWarningLevel_0;
+ break;
+ case '1':
+ WarningLevel = midlWarningLevel_1;
+ break;
+ case '2':
+ WarningLevel = midlWarningLevel_2;
+ break;
+ case '3':
+ WarningLevel = midlWarningLevel_3;
+ break;
+ case '4':
+ WarningLevel = midlWarningLevel_4;
+ break;
+ default:
+ found = false;
+ }
+ }
+ break;
+ }
+ if(!found)
+ warn_msg(WarnLogic, "Could not parse MIDL option: %s", option);
+ return true;
+}
+
+// VCLibrarianTool --------------------------------------------------
+VCLibrarianTool::VCLibrarianTool()
+ : IgnoreAllDefaultLibraries(unset),
+ SuppressStartupBanner(_True)
+{
+}
+
+// VCCustomBuildTool ------------------------------------------------
+VCCustomBuildTool::VCCustomBuildTool()
+{
+ ToolName = "VCCustomBuildTool";
+}
+
+// VCResourceCompilerTool -------------------------------------------
+VCResourceCompilerTool::VCResourceCompilerTool()
+ : Culture(rcUseDefault),
+ IgnoreStandardIncludePath(unset),
+ ShowProgress(linkProgressNotSet),
+ SuppressStartupBanner(unset)
+{
+ PreprocessorDefinitions = QStringList("NDEBUG");
+}
+
+// VCDeploymentTool --------------------------------------------
+VCDeploymentTool::VCDeploymentTool()
+ : RegisterOutput(registerNo)
+{
+ DeploymentTag = "DeploymentTool";
+ RemoteDirectory = "";
+}
+
+VCEventTool::VCEventTool(const QString &eventName)
+ : ExcludedFromBuild(unset)
+{
+ EventName = eventName;
+ ToolName = "VC";
+ ToolName += eventName;
+ ToolName += "Tool";
+}
+
+// VCPostBuildEventTool ---------------------------------------------
+VCPostBuildEventTool::VCPostBuildEventTool()
+ : VCEventTool("PostBuildEvent")
+{
+}
+
+// VCPreBuildEventTool ----------------------------------------------
+VCPreBuildEventTool::VCPreBuildEventTool()
+ : VCEventTool("PreBuildEvent")
+{
+}
+
+// VCPreLinkEventTool -----------------------------------------------
+VCPreLinkEventTool::VCPreLinkEventTool()
+ : VCEventTool("PreLinkEvent")
+{
+}
+
+// VCConfiguration --------------------------------------------------
+
+VCConfiguration::VCConfiguration()
+ : ATLMinimizesCRunTimeLibraryUsage(unset),
+ BuildBrowserInformation(unset),
+ CharacterSet(charSetNotSet),
+ ConfigurationType(typeApplication),
+ RegisterOutput(unset),
+ UseOfATL(useATLNotSet),
+ UseOfMfc(useMfcStdWin),
+ WholeProgramOptimization(unset)
+{
+ compiler.config = this;
+ linker.config = this;
+ idl.config = this;
+ custom.config = this;
+}
+
+// VCFilter ---------------------------------------------------------
+VCFilter::VCFilter()
+ : ParseFiles(unset),
+ Config(0)
+{
+ useCustomBuildTool = false;
+ useCompilerTool = false;
+}
+
+void VCFilter::addFile(const QString& filename)
+{
+ Files += VCFilterFile(filename);
+}
+
+void VCFilter::addFile(const VCFilterFile& fileInfo)
+{
+ Files += VCFilterFile(fileInfo);
+}
+
+void VCFilter::addFiles(const QStringList& fileList)
+{
+ for (int i = 0; i < fileList.count(); ++i)
+ addFile(fileList.at(i));
+}
+
+void VCFilter::modifyPCHstage(QString str)
+{
+ bool autogenSourceFile = Project->autogenPrecompCPP;
+ bool pchThroughSourceFile = !Project->precompCPP.isEmpty();
+ bool isCFile = false;
+ for (QStringList::Iterator it = Option::c_ext.begin(); it != Option::c_ext.end(); ++it) {
+ if (str.endsWith(*it)) {
+ isCFile = true;
+ break;
+ }
+ }
+ bool isHFile = Option::hasFileExtension(str, Option::h_ext) && (str == Project->precompH);
+ bool isCPPFile = pchThroughSourceFile && (str == Project->precompCPP);
+
+ if(!isCFile && !isHFile && !isCPPFile)
+ return;
+
+ if(isHFile && pchThroughSourceFile) {
+ if (autogenSourceFile) {
+ useCustomBuildTool = true;
+ QString toFile(Project->precompCPP);
+ CustomBuildTool.Description = "Generating precompiled header source file '" + toFile + "' ...";
+ CustomBuildTool.Outputs += toFile;
+
+ QStringList lines;
+ CustomBuildTool.CommandLine +=
+ "echo /*-------------------------------------------------------------------- >" + toFile;
+ lines << "* Precompiled header source file used by Visual Studio.NET to generate";
+ lines << "* the .pch file.";
+ lines << "*";
+ lines << "* Due to issues with the dependencies checker within the IDE, it";
+ lines << "* sometimes fails to recompile the PCH file, if we force the IDE to";
+ lines << "* create the PCH file directly from the header file.";
+ lines << "*";
+ lines << "* This file is auto-generated by qmake since no PRECOMPILED_SOURCE was";
+ lines << "* specified, and is used as the common stdafx.cpp. The file is only";
+ lines << QLatin1String("* generated when creating ")
+ + (Config->CompilerVersion < NET2010 ? ".vcproj" : ".vcxproj")
+ + " project files, and is not used for";
+ lines << "* command line compilations by nmake.";
+ lines << "*";
+ lines << "* WARNING: All changes made in this file will be lost.";
+ lines << "--------------------------------------------------------------------*/";
+ lines << "#include \"" + Project->precompHFilename + "\"";
+ foreach(QString line, lines)
+ CustomBuildTool.CommandLine += "echo " + line + ">>" + toFile;
+ }
+ return;
+ }
+
+ useCompilerTool = true;
+ // Setup PCH options
+ CompilerTool.UsePrecompiledHeader = (isCFile ? pchNone : pchCreateUsingSpecific);
+ CompilerTool.PrecompiledHeaderThrough = (isCPPFile ? Project->precompHFilename : QString("$(NOINHERIT)"));
+ CompilerTool.ForcedIncludeFiles = QStringList("$(NOINHERIT)");
+}
+
+bool VCFilter::addExtraCompiler(const VCFilterFile &info)
+{
+ const QStringList &extraCompilers = Project->extraCompilerSources.value(info.file);
+ if (extraCompilers.isEmpty())
+ return false;
+
+ QString inFile = info.file;
+
+ // is the extracompiler rule on a file with a built in compiler?
+ const QStringList &objectMappedFile = Project->extraCompilerOutputs[inFile];
+ bool hasBuiltIn = false;
+ if (!objectMappedFile.isEmpty()) {
+ hasBuiltIn = Project->hasBuiltinCompiler(objectMappedFile.at(0));
+// qDebug("*** Extra compiler file has object mapped file '%s' => '%s'", qPrintable(inFile), qPrintable(objectMappedFile.join(" ")));
+ }
+
+ CustomBuildTool.AdditionalDependencies.clear();
+ CustomBuildTool.CommandLine.clear();
+ CustomBuildTool.Description.clear();
+ CustomBuildTool.Outputs.clear();
+ CustomBuildTool.ToolPath.clear();
+ CustomBuildTool.ToolName = QLatin1String(_VCCustomBuildTool);
+
+ for (int x = 0; x < extraCompilers.count(); ++x) {
+ const QString &extraCompilerName = extraCompilers.at(x);
+
+ if (!Project->verifyExtraCompiler(extraCompilerName, inFile) && !hasBuiltIn)
+ continue;
+
+ // All information about the extra compiler
+ QString tmp_out = Project->project->first(extraCompilerName + ".output");
+ QString tmp_cmd = Project->project->variables()[extraCompilerName + ".commands"].join(" ");
+ QString tmp_cmd_name = Project->project->variables()[extraCompilerName + ".name"].join(" ");
+ QStringList tmp_dep = Project->project->variables()[extraCompilerName + ".depends"];
+ QString tmp_dep_cmd = Project->project->variables()[extraCompilerName + ".depend_command"].join(" ");
+ QStringList vars = Project->project->variables()[extraCompilerName + ".variables"];
+ QStringList configs = Project->project->variables()[extraCompilerName + ".CONFIG"];
+ bool combined = configs.indexOf("combine") != -1;
+
+ QString cmd, cmd_name, out;
+ QStringList deps, inputs;
+ // Variabel replacement of output name
+ out = Option::fixPathToTargetOS(
+ Project->replaceExtraCompilerVariables(tmp_out, inFile, QString()),
+ false);
+
+ // If file has built-in compiler, we've swapped the input and output of
+ // the command, as we in Visual Studio cannot have a Custom Buildstep on
+ // a file which uses a built-in compiler. We would in this case only get
+ // the result from the extra compiler. If 'hasBuiltIn' is true, we know
+ // that we're actually on the _output_file_ of the result, and we
+ // therefore swap inFile and out below, since the extra-compiler still
+ // must see it as the original way. If the result also has a built-in
+ // compiler, too bad..
+ if (hasBuiltIn) {
+ out = inFile;
+ inFile = objectMappedFile.at(0);
+ }
+
+ // Dependency for the output
+ if(!tmp_dep.isEmpty())
+ deps = tmp_dep;
+ if(!tmp_dep_cmd.isEmpty()) {
+ // Execute dependency command, and add every line as a dep
+ char buff[256];
+ QString dep_cmd = Project->replaceExtraCompilerVariables(tmp_dep_cmd,
+ Option::fixPathToLocalOS(inFile, true, false),
+ out);
+ if(Project->canExecute(dep_cmd)) {
+ dep_cmd.prepend(QLatin1String("cd ")
+ + Project->escapeFilePath(Option::fixPathToLocalOS(Option::output_dir, false))
+ + QLatin1String(" && "));
+ if(FILE *proc = QT_POPEN(dep_cmd.toLatin1().constData(), "r")) {
+ QString indeps;
+ while(!feof(proc)) {
+ int read_in = (int)fread(buff, 1, 255, proc);
+ if(!read_in)
+ break;
+ indeps += QByteArray(buff, read_in);
+ }
+ QT_PCLOSE(proc);
+ if(!indeps.isEmpty()) {
+ QStringList extradeps = indeps.split(QLatin1Char('\n'));
+ for (int i = 0; i < extradeps.count(); ++i) {
+ QString dd = extradeps.at(i).simplified();
+ if (!dd.isEmpty())
+ deps += Project->fileFixify(dd, QString(), Option::output_dir);
+ }
+ }
+ }
+ }
+ }
+ for (int i = 0; i < deps.count(); ++i)
+ deps[i] = Option::fixPathToTargetOS(
+ Project->replaceExtraCompilerVariables(deps.at(i), inFile, out),
+ false).trimmed();
+ // Command for file
+ if (combined) {
+ // Add dependencies for each file
+ QStringList tmp_in = Project->project->variables()[extraCompilerName + ".input"];
+ for (int a = 0; a < tmp_in.count(); ++a) {
+ const QStringList &files = Project->project->variables()[tmp_in.at(a)];
+ for (int b = 0; b < files.count(); ++b) {
+ deps += Project->findDependencies(files.at(b));
+ inputs += Option::fixPathToTargetOS(files.at(b), false);
+ }
+ }
+ deps += inputs; // input files themselves too..
+
+ // Replace variables for command w/all input files
+ // ### join gives path issues with directories containing spaces!
+ cmd = Project->replaceExtraCompilerVariables(tmp_cmd,
+ inputs.join(" "),
+ out);
+ } else {
+ deps += inFile; // input file itself too..
+ cmd = Project->replaceExtraCompilerVariables(tmp_cmd,
+ inFile,
+ out);
+ }
+ // Name for command
+ if(!tmp_cmd_name.isEmpty()) {
+ cmd_name = Project->replaceExtraCompilerVariables(tmp_cmd_name, inFile, out);
+ } else {
+ int space = cmd.indexOf(' ');
+ if(space != -1)
+ cmd_name = cmd.left(space);
+ else
+ cmd_name = cmd;
+ if((cmd_name[0] == '\'' || cmd_name[0] == '"') &&
+ cmd_name[0] == cmd_name[cmd_name.length()-1])
+ cmd_name = cmd_name.mid(1,cmd_name.length()-2);
+ }
+
+ // Fixify paths
+ for (int i = 0; i < deps.count(); ++i)
+ deps[i] = Option::fixPathToTargetOS(deps[i], false);
+
+
+ // Output in info.additionalFile -----------
+ if (!CustomBuildTool.Description.isEmpty())
+ CustomBuildTool.Description += ", ";
+ CustomBuildTool.Description += cmd_name;
+ CustomBuildTool.CommandLine += VCToolBase::fixCommandLine(cmd.trimmed());
+ int space = cmd.indexOf(' ');
+ QFileInfo finf(cmd.left(space));
+ if (CustomBuildTool.ToolPath.isEmpty())
+ CustomBuildTool.ToolPath += Option::fixPathToTargetOS(finf.path());
+ CustomBuildTool.Outputs += out;
+
+ deps += CustomBuildTool.AdditionalDependencies;
+ deps += cmd.left(cmd.indexOf(' '));
+ // Make sure that all deps are only once
+ QMap<QString, bool> uniqDeps;
+ for (int c = 0; c < deps.count(); ++c) {
+ QString aDep = deps.at(c).trimmed();
+ if (!aDep.isEmpty())
+ uniqDeps[aDep] = false;
+ }
+ CustomBuildTool.AdditionalDependencies = uniqDeps.keys();
+ }
+
+ // Ensure that none of the output files are also dependencies. Or else, the custom buildstep
+ // will be rebuild every time, even if nothing has changed.
+ foreach(QString output, CustomBuildTool.Outputs) {
+ CustomBuildTool.AdditionalDependencies.removeAll(output);
+ }
+
+ useCustomBuildTool = !CustomBuildTool.CommandLine.isEmpty();
+ return useCustomBuildTool;
+}
+
+// VCProjectSingleConfig --------------------------------------------
+VCFilter& VCProjectSingleConfig::filterForExtraCompiler(const QString &compilerName)
+{
+ for (int i = 0; i < ExtraCompilersFiles.count(); ++i)
+ if (ExtraCompilersFiles.at(i).Name == compilerName)
+ return ExtraCompilersFiles[i];
+
+ static VCFilter nullFilter;
+ return nullFilter;
+}
+
+// Tree file generation ---------------------------------------------
+void TreeNode::generateXML(XmlOutput &xml, const QString &tagName, VCProject &tool, const QString &filter) {
+ if (children.size()) {
+ // Filter
+ ChildrenMap::ConstIterator it, end = children.constEnd();
+ if (!tagName.isEmpty()) {
+ xml << tag("Filter")
+ << attr("Name", tagName)
+ << attr("Filter", "");
+ }
+ // First round, do nested filters
+ for (it = children.constBegin(); it != end; ++it)
+ if ((*it)->children.size())
+ (*it)->generateXML(xml, it.key(), tool, filter);
+ // Second round, do leafs
+ for (it = children.constBegin(); it != end; ++it)
+ if (!(*it)->children.size())
+ (*it)->generateXML(xml, it.key(), tool, filter);
+
+ if (!tagName.isEmpty())
+ xml << closetag("Filter");
+ } else {
+ // Leaf
+ VCProjectWriter::outputFileConfigs(tool, xml, info, filter);
+ }
+}
+
+// Flat file generation ---------------------------------------------
+void FlatNode::generateXML(XmlOutput &xml, const QString &/*tagName*/, VCProject &tool, const QString &filter) {
+ if (children.size()) {
+ ChildrenMapFlat::ConstIterator it = children.constBegin();
+ ChildrenMapFlat::ConstIterator end = children.constEnd();
+ for (; it != end; ++it) {
+ VCProjectWriter::outputFileConfigs(tool, xml, (*it), filter);
+ }
+ }
+}
+
+void VCProjectWriter::write(XmlOutput &xml, VCProjectSingleConfig &tool)
+{
+ xml << decl("1.0", "Windows-1252")
+ << tag(_VisualStudioProject)
+ << attrS(_ProjectType, "Visual C++")
+ << attrS(_Version, tool.Version)
+ << attrS(_Name, tool.Name)
+ << attrS(_ProjectGUID, tool.ProjectGUID)
+ << attrS(_Keyword, tool.Keyword)
+ << attrS(_SccProjectName, tool.SccProjectName)
+ << attrS(_SccLocalPath, tool.SccLocalPath)
+ << tag(_Platforms)
+ << tag(_Platform)
+ << attrS(_Name, tool.PlatformName)
+ << closetag(_Platforms)
+ << tag(_Configurations);
+ write(xml, tool.Configuration);
+ xml << closetag(_Configurations)
+ << tag(q_Files);
+ // Add this configuration into a multi-config project, since that's where we have the flat/tree
+ // XML output functionality
+ VCProject tempProj;
+ tempProj.SingleProjects += tool;
+ outputFilter(tempProj, xml, "Sources");
+ outputFilter(tempProj, xml, "Headers");
+ outputFilter(tempProj, xml, "GeneratedFiles");
+ outputFilter(tempProj, xml, "LexYaccFiles");
+ outputFilter(tempProj, xml, "TranslationFiles");
+ outputFilter(tempProj, xml, "FormFiles");
+ outputFilter(tempProj, xml, "ResourceFiles");
+ for (int x = 0; x < tempProj.ExtraCompilers.count(); ++x) {
+ outputFilter(tempProj, xml, tempProj.ExtraCompilers.at(x));
+ }
+ outputFilter(tempProj, xml, "RootFiles");
+ xml << closetag(q_Files)
+ << tag(_Globals)
+ << data(); // No "/>" end tag
+}
+
+void VCProjectWriter::write(XmlOutput &xml, VCProject &tool)
+{
+ if (tool.SingleProjects.count() == 0) {
+ warn_msg(WarnLogic, "Generator: .NET: no single project in merge project, no output");
+ return;
+ }
+
+ xml << decl("1.0", "Windows-1252")
+ << tag(_VisualStudioProject)
+ << attrS(_ProjectType, "Visual C++")
+ << attrS(_Version, tool.Version)
+ << attrS(_Name, tool.Name)
+ << attrS(_ProjectGUID, tool.ProjectGUID)
+ << attrS(_Keyword, tool.Keyword)
+ << attrS(_SccProjectName, tool.SccProjectName)
+ << attrS(_SccLocalPath, tool.SccLocalPath)
+ << tag(_Platforms)
+ << tag(_Platform)
+ << attrS(_Name, tool.PlatformName)
+ << closetag(_Platforms)
+ << tag(_Configurations);
+ // Output each configuration
+ for (int i = 0; i < tool.SingleProjects.count(); ++i)
+ write(xml, tool.SingleProjects.at(i).Configuration);
+ xml << closetag(_Configurations)
+ << tag(q_Files);
+ outputFilter(tool, xml, "Sources");
+ outputFilter(tool, xml, "Headers");
+ outputFilter(tool, xml, "GeneratedFiles");
+ outputFilter(tool, xml, "LexYaccFiles");
+ outputFilter(tool, xml, "TranslationFiles");
+ outputFilter(tool, xml, "FormFiles");
+ outputFilter(tool, xml, "ResourceFiles");
+ for (int x = 0; x < tool.ExtraCompilers.count(); ++x) {
+ outputFilter(tool, xml, tool.ExtraCompilers.at(x));
+ }
+ outputFilter(tool, xml, "RootFiles");
+ xml << closetag(q_Files)
+ << tag(_Globals)
+ << data(); // No "/>" end tag
+}
+
+void VCProjectWriter::write(XmlOutput &xml, const VCCLCompilerTool &tool)
+{
+ xml << tag(_Tool)
+ << attrS(_Name, _VCCLCompilerTool)
+ << attrX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories)
+ << attrX(_AdditionalOptions, tool.AdditionalOptions, " ")
+ << attrX(_AdditionalUsingDirectories, tool.AdditionalUsingDirectories)
+ << attrS(_AssemblerListingLocation, tool.AssemblerListingLocation)
+ << attrE(_AssemblerOutput, tool.AssemblerOutput, /*ifNot*/ asmListingNone)
+ << attrE(_BasicRuntimeChecks, tool.BasicRuntimeChecks, /*ifNot*/ runtimeBasicCheckNone)
+ << attrE(_BrowseInformation, tool.BrowseInformation, /*ifNot*/ brInfoNone)
+ << attrS(_BrowseInformationFile, tool.BrowseInformationFile)
+ << attrT(_BufferSecurityCheck, tool.BufferSecurityCheck)
+ << attrE(_CallingConvention, tool.CallingConvention, /*ifNot*/ callConventionDefault)
+ << attrE(_CompileAs, tool.CompileAs, compileAsDefault)
+ << attrE(_CompileAsManaged, tool.CompileAsManaged, /*ifNot*/ managedDefault)
+ << attrT(_CompileOnly, tool.CompileOnly)
+ << attrE(_DebugInformationFormat, tool.DebugInformationFormat, /*ifNot*/ debugUnknown)
+ << attrT(_DefaultCharIsUnsigned, tool.DefaultCharIsUnsigned)
+ << attrT(_Detect64BitPortabilityProblems, tool.Detect64BitPortabilityProblems)
+ << attrT(_DisableLanguageExtensions, tool.DisableLanguageExtensions)
+ << attrX(_DisableSpecificWarnings, tool.DisableSpecificWarnings)
+ << attrE(_EnableEnhancedInstructionSet, tool.EnableEnhancedInstructionSet, /*ifnot*/ archNotSet)
+ << attrT(_EnableFiberSafeOptimizations, tool.EnableFiberSafeOptimizations)
+ << attrT(_EnableFunctionLevelLinking, tool.EnableFunctionLevelLinking)
+ << attrT(_EnableIntrinsicFunctions, tool.EnableIntrinsicFunctions)
+ << xformExceptionHandlingNET2005(tool.ExceptionHandling, tool.config->CompilerVersion)
+ << attrT(_ExpandAttributedSource, tool.ExpandAttributedSource)
+ << attrE(_FavorSizeOrSpeed, tool.FavorSizeOrSpeed, /*ifNot*/ favorNone)
+
+ << attrE(_FloatingPointModel, tool.FloatingPointModel, /*ifNot*/ floatingPointNotSet)
+ << attrT(_FloatingPointExceptions, tool.FloatingPointExceptions)
+
+ << attrT(_ForceConformanceInForLoopScope, tool.ForceConformanceInForLoopScope)
+ << attrX(_ForcedIncludeFiles, tool.ForcedIncludeFiles)
+ << attrX(_ForcedUsingFiles, tool.ForcedUsingFiles)
+ << attrE(_GeneratePreprocessedFile, tool.GeneratePreprocessedFile, /*ifNot*/ preprocessUnknown)
+ << attrT(_GlobalOptimizations, tool.GlobalOptimizations)
+ << attrT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath)
+ << attrT(_ImproveFloatingPointConsistency, tool.ImproveFloatingPointConsistency)
+ << attrE(_InlineFunctionExpansion, tool.InlineFunctionExpansion, /*ifNot*/ expandDefault)
+ << attrT(_KeepComments, tool.KeepComments)
+ << attrT(_MinimalRebuild, tool.MinimalRebuild)
+ << attrS(_ObjectFile, tool.ObjectFile)
+ << attrT(_OmitFramePointers, tool.OmitFramePointers)
+ << attrT(_OpenMP, tool.OpenMP)
+ << attrE(_Optimization, tool.Optimization, /*ifNot*/ optimizeDefault)
+ << attrE(_OptimizeForProcessor, tool.OptimizeForProcessor, /*ifNot*/ procOptimizeBlended)
+ << attrT(_OptimizeForWindowsApplication, tool.OptimizeForWindowsApplication)
+ << attrS(_OutputFile, tool.OutputFile)
+ << attrS(_PrecompiledHeaderFile, tool.PrecompiledHeaderFile)
+ << attrS(_PrecompiledHeaderThrough, tool.PrecompiledHeaderThrough)
+ << attrX(_PreprocessorDefinitions, tool.PreprocessorDefinitions)
+ << (tool.ProgramDataBaseFileName.isNull() ? noxml() : attr(_ProgramDataBaseFileName, tool.ProgramDataBaseFileName))
+ << attrE(_RuntimeLibrary, tool.RuntimeLibrary, /*ifNot*/ rtUnknown)
+ << attrT(_RuntimeTypeInfo, tool.RuntimeTypeInfo)
+ << attrT(_ShowIncludes, tool.ShowIncludes)
+ << attrT(_SmallerTypeCheck, tool.SmallerTypeCheck)
+ << attrT(_StringPooling, tool.StringPooling)
+ << attrE(_StructMemberAlignment, tool.StructMemberAlignment, /*ifNot*/ alignNotSet)
+ << attrT(_SuppressStartupBanner, tool.SuppressStartupBanner)
+ << attrT(_TreatWChar_tAsBuiltInType, tool.TreatWChar_tAsBuiltInType)
+ << attrT(_TurnOffAssemblyGeneration, tool.TurnOffAssemblyGeneration)
+ << attrT(_UndefineAllPreprocessorDefinitions, tool.UndefineAllPreprocessorDefinitions)
+ << attrX(_UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions)
+ << xformUsePrecompiledHeaderForNET2005(tool.UsePrecompiledHeader, tool.config->CompilerVersion)
+ << attrT(_WarnAsError, tool.WarnAsError)
+ << attrE(_WarningLevel, tool.WarningLevel, /*ifNot*/ warningLevelUnknown)
+ << attrT(_WholeProgramOptimization, tool.WholeProgramOptimization)
+ << attrE(_CompileForArchitecture, tool.CompileForArchitecture, /*ifNot*/ archUnknown)
+ << attrT(_InterworkCalls, tool.InterworkCalls)
+
+ << closetag(_Tool);
+}
+
+void VCProjectWriter::write(XmlOutput &xml, const VCLinkerTool &tool)
+{
+ xml << tag(_Tool)
+ << attrS(_Name, _VCLinkerTool)
+ << attrX(_AdditionalDependencies, tool.AdditionalDependencies, " ")
+ << attrX(_AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories)
+ << attrX(_AdditionalOptions, tool.AdditionalOptions, " ")
+ << attrX(_AddModuleNamesToAssembly, tool.AddModuleNamesToAssembly)
+ << attrS(_BaseAddress, tool.BaseAddress)
+ << attrX(_DelayLoadDLLs, tool.DelayLoadDLLs)
+ << attrE(_EnableCOMDATFolding, tool.EnableCOMDATFolding, /*ifNot*/ optFoldingDefault)
+ << attrS(_EntryPointSymbol, tool.EntryPointSymbol)
+ << attrX(_ForceSymbolReferences, tool.ForceSymbolReferences)
+ << attrS(_FunctionOrder, tool.FunctionOrder)
+ << attrT(_GenerateDebugInformation, tool.GenerateDebugInformation)
+ << attrT(_GenerateMapFile, tool.GenerateMapFile)
+ << attrL(_HeapCommitSize, tool.HeapCommitSize, /*ifNot*/ -1)
+ << attrL(_HeapReserveSize, tool.HeapReserveSize, /*ifNot*/ -1)
+ << attrT(_IgnoreAllDefaultLibraries, tool.IgnoreAllDefaultLibraries)
+ << attrX(_IgnoreDefaultLibraryNames, tool.IgnoreDefaultLibraryNames)
+ << attrT(_IgnoreEmbeddedIDL, tool.IgnoreEmbeddedIDL)
+ << attrT(_IgnoreImportLibrary, tool.IgnoreImportLibrary)
+ << attrS(_ImportLibrary, tool.ImportLibrary)
+ << attrE(_LargeAddressAware, tool.LargeAddressAware, /*ifNot*/ addrAwareDefault)
+ << attrT(_LinkDLL, tool.LinkDLL)
+ << attrE(_LinkIncremental, tool.LinkIncremental, /*ifNot*/ linkIncrementalDefault)
+ << attrE(_LinkTimeCodeGeneration, tool.LinkTimeCodeGeneration)
+ << attrS(_LinkToManagedResourceFile, tool.LinkToManagedResourceFile)
+ << attrT(_MapExports, tool.MapExports)
+ << attrS(_MapFileName, tool.MapFileName)
+ << attrT(_MapLines, tool.MapLines)
+ << attrS(_MergedIDLBaseFileName, tool.MergedIDLBaseFileName)
+ << attrS(_MergeSections, tool.MergeSections)
+ << attrS(_MidlCommandFile, tool.MidlCommandFile)
+ << attrS(_ModuleDefinitionFile, tool.ModuleDefinitionFile)
+ << attrE(_OptimizeForWindows98, tool.OptimizeForWindows98, /*ifNot*/ optWin98Default)
+ << attrE(_OptimizeReferences, tool.OptimizeReferences, /*ifNot*/ optReferencesDefault)
+ << attrS(_OutputFile, tool.OutputFile)
+ << attr(_ProgramDatabaseFile, tool.ProgramDatabaseFile)
+ << attrT(_RegisterOutput, tool.RegisterOutput)
+ << attrT(_ResourceOnlyDLL, tool.ResourceOnlyDLL)
+ << attrT(_SetChecksum, tool.SetChecksum)
+ << attrE(_ShowProgress, tool.ShowProgress, /*ifNot*/ linkProgressNotSet)
+ << attrL(_StackCommitSize, tool.StackCommitSize, /*ifNot*/ -1)
+ << attrL(_StackReserveSize, tool.StackReserveSize, /*ifNot*/ -1)
+ << attrS(_StripPrivateSymbols, tool.StripPrivateSymbols)
+ << attrE(_SubSystem, tool.SubSystem)
+ << attrT(_SupportUnloadOfDelayLoadedDLL, tool.SupportUnloadOfDelayLoadedDLL)
+ << attrT(_SuppressStartupBanner, tool.SuppressStartupBanner)
+ << attrT(_SwapRunFromCD, tool.SwapRunFromCD)
+ << attrT(_SwapRunFromNet, tool.SwapRunFromNet)
+ << attrE(_TargetMachine, tool.TargetMachine, /*ifNot*/ machineNotSet)
+ << attrE(_TerminalServerAware, tool.TerminalServerAware, /*ifNot*/ termSvrAwareDefault)
+ << attrT(_TurnOffAssemblyGeneration, tool.TurnOffAssemblyGeneration)
+ << attrS(_TypeLibraryFile, tool.TypeLibraryFile)
+ << attrL(_TypeLibraryResourceID, tool.TypeLibraryResourceID, /*ifNot*/ rcUseDefault)
+ << attrS(_Version, tool.Version)
+ << closetag(_Tool);
+}
+
+void VCProjectWriter::write(XmlOutput &xml, const VCMIDLTool &tool)
+{
+ xml << tag(_Tool)
+ << attrS(_Name, _VCMIDLTool)
+ << attrX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories)
+ << attrX(_AdditionalOptions, tool.AdditionalOptions, " ")
+ << attrX(_CPreprocessOptions, tool.CPreprocessOptions)
+ << attrE(_DefaultCharType, tool.DefaultCharType)
+ << attrS(_DLLDataFileName, tool.DLLDataFileName)
+ << attrE(_EnableErrorChecks, tool.EnableErrorChecks)
+ << attrT(_ErrorCheckAllocations, tool.ErrorCheckAllocations)
+ << attrT(_ErrorCheckBounds, tool.ErrorCheckBounds)
+ << attrT(_ErrorCheckEnumRange, tool.ErrorCheckEnumRange)
+ << attrT(_ErrorCheckRefPointers, tool.ErrorCheckRefPointers)
+ << attrT(_ErrorCheckStubData, tool.ErrorCheckStubData)
+ << attrX(_FullIncludePath, tool.FullIncludePath)
+ << attrT(_GenerateStublessProxies, tool.GenerateStublessProxies)
+ << attrT(_GenerateTypeLibrary, tool.GenerateTypeLibrary)
+ << attrS(_HeaderFileName, tool.HeaderFileName)
+ << attrT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath)
+ << attrS(_InterfaceIdentifierFileName, tool.InterfaceIdentifierFileName)
+ << attrT(_MkTypLibCompatible, tool.MkTypLibCompatible)
+ << attrS(_OutputDirectory, tool.OutputDirectory)
+ << attrX(_PreprocessorDefinitions, tool.PreprocessorDefinitions)
+ << attrS(_ProxyFileName, tool.ProxyFileName)
+ << attrS(_RedirectOutputAndErrors, tool.RedirectOutputAndErrors)
+ << attrE(_StructMemberAlignment, tool.StructMemberAlignment, /*ifNot*/ midlAlignNotSet)
+ << attrT(_SuppressStartupBanner, tool.SuppressStartupBanner)
+ << attrE(_TargetEnvironment, tool.TargetEnvironment, /*ifNot*/ midlTargetNotSet)
+ << attrS(_TypeLibraryName, tool.TypeLibraryName)
+ << attrX(_UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions)
+ << attrT(_ValidateParameters, tool.ValidateParameters)
+ << attrT(_WarnAsError, tool.WarnAsError)
+ << attrE(_WarningLevel, tool.WarningLevel)
+ << closetag(_Tool);
+}
+
+void VCProjectWriter::write(XmlOutput &xml, const VCCustomBuildTool &tool)
+{
+ xml << tag(_Tool)
+ << attrS(_Name, tool.ToolName)
+ << attrX(_AdditionalDependencies, tool.AdditionalDependencies, ";")
+ << attrS(_CommandLine, tool.CommandLine.join(vcCommandSeparator()))
+ << attrS(_Description, tool.Description)
+ << attrX(_Outputs, tool.Outputs, ";")
+ << attrS(_Path, tool.ToolPath)
+ << closetag(_Tool);
+}
+
+void VCProjectWriter::write(XmlOutput &xml, const VCLibrarianTool &tool)
+{
+ xml
+ << tag(_Tool)
+ << attrS(_Name, _VCLibrarianTool)
+ << attrX(_AdditionalDependencies, tool.AdditionalDependencies)
+ << attrX(_AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories)
+ << attrX(_AdditionalOptions, tool.AdditionalOptions, " ")
+ << attrX(_ExportNamedFunctions, tool.ExportNamedFunctions)
+ << attrX(_ForceSymbolReferences, tool.ForceSymbolReferences)
+ << attrT(_IgnoreAllDefaultLibraries, tool.IgnoreAllDefaultLibraries)
+ << attrX(_IgnoreDefaultLibraryNames, tool.IgnoreDefaultLibraryNames)
+ << attrS(_ModuleDefinitionFile, tool.ModuleDefinitionFile)
+ << attrS(_OutputFile, tool.OutputFile)
+ << attrT(_SuppressStartupBanner, tool.SuppressStartupBanner)
+ << closetag(_Tool);
+}
+
+void VCProjectWriter::write(XmlOutput &xml, const VCResourceCompilerTool &tool)
+{
+ xml
+ << tag(_Tool)
+ << attrS(_Name, _VCResourceCompilerTool)
+ << attrS(_Path, tool.ToolPath)
+ << attrX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories)
+ << attrX(_AdditionalOptions, tool.AdditionalOptions, " ")
+ << attrE(_Culture, tool.Culture, /*ifNot*/ rcUseDefault)
+ << attrX(_FullIncludePath, tool.FullIncludePath)
+ << attrT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath)
+ << attrX(_PreprocessorDefinitions, tool.PreprocessorDefinitions)
+ << attrS(_ResourceOutputFileName, tool.ResourceOutputFileName)
+ << attrE(_ShowProgress, tool.ShowProgress, /*ifNot*/ linkProgressNotSet)
+ << closetag(_Tool);
+}
+
+void VCProjectWriter::write(XmlOutput &xml, const VCEventTool &tool)
+{
+ xml
+ << tag(_Tool)
+ << attrS(_Name, tool.ToolName)
+ << attrS(_Path, tool.ToolPath)
+ << attrS(_CommandLine, tool.CommandLine.join(vcCommandSeparator()))
+ << attrS(_Description, tool.Description)
+ << attrT(_ExcludedFromBuild, tool.ExcludedFromBuild)
+ << closetag(_Tool);
+}
+
+void VCProjectWriter::write(XmlOutput &xml, const VCDeploymentTool &tool)
+{
+ if (tool.AdditionalFiles.isEmpty())
+ return;
+ xml << tag(tool.DeploymentTag)
+ << attrS(_RemoteDirectory, tool.RemoteDirectory)
+ << attrE(_RegisterOutput, tool.RegisterOutput)
+ << attrS(_AdditionalFiles, tool.AdditionalFiles)
+ << closetag(tool.DeploymentTag);
+}
+
+void VCProjectWriter::write(XmlOutput &xml, const VCConfiguration &tool)
+{
+ xml << tag(_Configuration)
+ << attrS(_Name, tool.Name)
+ << attrS(_OutputDirectory, tool.OutputDirectory)
+ << attrT(_ATLMinimizesCRunTimeLibraryUsage, tool.ATLMinimizesCRunTimeLibraryUsage)
+ << attrT(_BuildBrowserInformation, tool.BuildBrowserInformation)
+ << attrE(_CharacterSet, tool.CharacterSet, /*ifNot*/ charSetNotSet)
+ << attrE(_ConfigurationType, tool.ConfigurationType)
+ << attrS(_DeleteExtensionsOnClean, tool.DeleteExtensionsOnClean)
+ << attrS(_ImportLibrary, tool.ImportLibrary)
+ << attrS(_IntermediateDirectory, tool.IntermediateDirectory)
+ << attrS(_PrimaryOutput, tool.PrimaryOutput)
+ << attrS(_ProgramDatabase, tool.ProgramDatabase)
+ << attrT(_RegisterOutput, tool.RegisterOutput)
+ << attrE(_UseOfATL, tool.UseOfATL, /*ifNot*/ useATLNotSet)
+ << attrE(_UseOfMfc, tool.UseOfMfc)
+ << attrT(_WholeProgramOptimization, tool.WholeProgramOptimization);
+ write(xml, tool.compiler);
+ write(xml, tool.custom);
+ if (tool.ConfigurationType == typeStaticLibrary)
+ write(xml, tool.librarian);
+ else
+ write(xml, tool.linker);
+ write(xml, tool.idl);
+ write(xml, tool.postBuild);
+ write(xml, tool.preBuild);
+ write(xml, tool.preLink);
+ write(xml, tool.resource);
+ write(xml, tool.deployment);
+ xml << closetag(_Configuration);
+}
+
+void VCProjectWriter::write(XmlOutput &xml, VCFilter &tool)
+{
+ if(!tool.Files.count())
+ return;
+
+ if (!tool.Name.isEmpty()) {
+ xml << tag(_Filter)
+ << attrS(_Name, tool.Name)
+ << attrS(_Filter, tool.Filter)
+ << attrS(_UniqueIdentifier, tool.Guid)
+ << attrT(_ParseFiles, tool.ParseFiles);
+ }
+ for (int i = 0; i < tool.Files.count(); ++i) {
+ const VCFilterFile &info = tool.Files.at(i);
+ xml << tag(q_File)
+ << attrS(_RelativePath, Option::fixPathToLocalOS(info.file))
+ << data(); // In case no custom builds, to avoid "/>" endings
+ outputFileConfig(tool, xml, tool.Files.at(i).file);
+ xml << closetag(q_File);
+ }
+ if (!tool.Name.isEmpty())
+ xml << closetag(_Filter);
+}
+
+// outputs a given filter for all existing configurations of a project
+void VCProjectWriter::outputFilter(VCProject &project, XmlOutput &xml, const QString &filtername)
+{
+ Node *root;
+ if (project.SingleProjects.at(0).flat_files)
+ root = new FlatNode;
+ else
+ root = new TreeNode;
+
+ QString name, extfilter, guid;
+ triState parse;
+
+ for (int i = 0; i < project.SingleProjects.count(); ++i) {
+ VCFilter filter;
+ const VCProjectSingleConfig &projectSingleConfig = project.SingleProjects.at(i);
+ if (filtername == "RootFiles") {
+ filter = projectSingleConfig.RootFiles;
+ } else if (filtername == "Sources") {
+ filter = projectSingleConfig.SourceFiles;
+ } else if (filtername == "Headers") {
+ filter = projectSingleConfig.HeaderFiles;
+ } else if (filtername == "GeneratedFiles") {
+ filter = projectSingleConfig.GeneratedFiles;
+ } else if (filtername == "LexYaccFiles") {
+ filter = projectSingleConfig.LexYaccFiles;
+ } else if (filtername == "TranslationFiles") {
+ filter = projectSingleConfig.TranslationFiles;
+ } else if (filtername == "FormFiles") {
+ filter = projectSingleConfig.FormFiles;
+ } else if (filtername == "ResourceFiles") {
+ filter = projectSingleConfig.ResourceFiles;
+ } else {
+ // ExtraCompilers
+ filter = project.SingleProjects[i].filterForExtraCompiler(filtername);
+ }
+
+ // Merge all files in this filter to root tree
+ for (int x = 0; x < filter.Files.count(); ++x)
+ root->addElement(filter.Files.at(x));
+
+ // Save filter setting from first filter. Next filters
+ // may differ but we cannot handle that. (ex. extfilter)
+ if (name.isEmpty()) {
+ name = filter.Name;
+ extfilter = filter.Filter;
+ parse = filter.ParseFiles;
+ guid = filter.Guid;
+ }
+ }
+
+ if (!root->hasElements())
+ return;
+
+ // Actual XML output ----------------------------------
+ if (!name.isEmpty()) {
+ xml << tag(_Filter)
+ << attrS(_Name, name)
+ << attrS(_Filter, extfilter)
+ << attrS(_UniqueIdentifier, guid)
+ << attrT(_ParseFiles, parse);
+ }
+ root->generateXML(xml, "", project, filtername); // output root tree
+ if (!name.isEmpty())
+ xml << closetag(_Filter);
+}
+
+// Output all configurations (by filtername) for a file (by info)
+// A filters config output is in VCFilter.outputFileConfig()
+void VCProjectWriter::outputFileConfigs(VCProject &project, XmlOutput &xml, const VCFilterFile &info, const QString &filtername)
+{
+ xml << tag(q_File)
+ << attrS(_RelativePath, Option::fixPathToLocalOS(info.file));
+ for (int i = 0; i < project.SingleProjects.count(); ++i) {
+ VCFilter filter;
+ const VCProjectSingleConfig &projectSingleConfig = project.SingleProjects.at(i);
+ if (filtername == "RootFiles") {
+ filter = projectSingleConfig.RootFiles;
+ } else if (filtername == "Sources") {
+ filter = projectSingleConfig.SourceFiles;
+ } else if (filtername == "Headers") {
+ filter = projectSingleConfig.HeaderFiles;
+ } else if (filtername == "GeneratedFiles") {
+ filter = projectSingleConfig.GeneratedFiles;
+ } else if (filtername == "LexYaccFiles") {
+ filter = projectSingleConfig.LexYaccFiles;
+ } else if (filtername == "TranslationFiles") {
+ filter = projectSingleConfig.TranslationFiles;
+ } else if (filtername == "FormFiles") {
+ filter = projectSingleConfig.FormFiles;
+ } else if (filtername == "ResourceFiles") {
+ filter = projectSingleConfig.ResourceFiles;
+ } else {
+ // ExtraCompilers
+ filter = project.SingleProjects[i].filterForExtraCompiler(filtername);
+ }
+
+ if (filter.Config) // only if the filter is not empty
+ outputFileConfig(filter, xml, info.file);
+ }
+ xml << closetag(q_File);
+}
+
+void VCProjectWriter::outputFileConfig(VCFilter &filter, XmlOutput &xml, const QString &filename)
+{
+ // Clearing each filter tool
+ filter.useCustomBuildTool = false;
+ filter.useCompilerTool = false;
+ filter.CustomBuildTool = VCCustomBuildTool();
+ filter.CompilerTool = VCCLCompilerTool();
+
+ // Unset some default options
+ filter.CustomBuildTool.config = filter.Config;
+ filter.CompilerTool.BufferSecurityCheck = unset;
+ filter.CompilerTool.DebugInformationFormat = debugUnknown;
+ filter.CompilerTool.ExceptionHandling = ehDefault;
+ filter.CompilerTool.GeneratePreprocessedFile = preprocessUnknown;
+ filter.CompilerTool.Optimization = optimizeDefault;
+ filter.CompilerTool.ProgramDataBaseFileName.clear();
+ filter.CompilerTool.RuntimeLibrary = rtUnknown;
+ filter.CompilerTool.WarningLevel = warningLevelUnknown;
+ filter.CompilerTool.config = filter.Config;
+
+ bool inBuild = false;
+ VCFilterFile info;
+ for (int i = 0; i < filter.Files.count(); ++i) {
+ if (filter.Files.at(i).file == filename) {
+ info = filter.Files.at(i);
+ inBuild = true;
+ }
+ }
+ inBuild &= !info.excludeFromBuild;
+
+ if (inBuild) {
+ filter.addExtraCompiler(info);
+ if(filter.Project->usePCH)
+ filter.modifyPCHstage(info.file);
+ } else {
+ // Excluded files uses an empty compiler stage
+ if(info.excludeFromBuild)
+ filter.useCompilerTool = true;
+ }
+
+ // Actual XML output ----------------------------------
+ if (filter.useCustomBuildTool || filter.useCompilerTool || !inBuild) {
+ xml << tag(_FileConfiguration)
+ << attr(_Name, filter.Config->Name)
+ << (!inBuild ? attrS(_ExcludedFromBuild, "true") : noxml());
+ if (filter.useCustomBuildTool)
+ filter.Project->projectWriter->write(xml, filter.CustomBuildTool);
+ if (filter.useCompilerTool)
+ filter.Project->projectWriter->write(xml, filter.CompilerTool);
+ xml << closetag(_FileConfiguration);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/qmake/generators/win32/msvc_objectmodel.h b/qmake/generators/win32/msvc_objectmodel.h
new file mode 100644
index 0000000000..3e62fb41ee
--- /dev/null
+++ b/qmake/generators/win32/msvc_objectmodel.h
@@ -0,0 +1,1141 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the qmake application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MSVC_OBJECTMODEL_H
+#define MSVC_OBJECTMODEL_H
+
+#include "project.h"
+#include "xmloutput.h"
+#include <qatomic.h>
+#include <qlist.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qmap.h>
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+enum DotNET {
+ NETUnknown = 0,
+ NET2002 = 0x70,
+ NET2003 = 0x71,
+ NET2005 = 0x80,
+ NET2008 = 0x90,
+ NET2010 = 0xa0
+};
+
+/*
+ This Object model is of course VERY simplyfied,
+ and does not actually follow the original MSVC
+ object model. However, it fulfilles the basic
+ needs for qmake
+*/
+
+/*
+ If a triState value is 'unset' then the
+ corresponding property is not in the output,
+ forcing the tool to utilize default values.
+ False/True values will be in the output...
+*/
+enum customBuildCheck {
+ none,
+ mocSrc,
+ mocHdr,
+ lexyacc
+};
+enum triState {
+ unset = -1,
+ _False = 0,
+ _True = 1
+};
+
+triState operator!(const triState &rhs);
+
+enum addressAwarenessType {
+ addrAwareDefault,
+ addrAwareNoLarge,
+ addrAwareLarge
+};
+enum asmListingOption {
+ asmListingNone,
+ asmListingAssemblyOnly,
+ asmListingAsmMachineSrc,
+ asmListingAsmMachine,
+ asmListingAsmSrc
+};
+enum basicRuntimeCheckOption {
+ runtimeBasicCheckNone,
+ runtimeCheckStackFrame,
+ runtimeCheckUninitVariables,
+ runtimeBasicCheckAll
+};
+enum browseInfoOption {
+ brInfoNone,
+ brAllInfo,
+ brNoLocalSymbols
+};
+enum callingConventionOption {
+ callConventionDefault = -1,
+ callConventionCDecl,
+ callConventionFastCall,
+ callConventionStdCall
+};
+enum charSet {
+ charSetNotSet,
+ charSetUnicode,
+ charSetMBCS
+};
+enum compileAsManagedOptions {
+ managedDefault = -1, // Was: noAssembly
+ managedAssembly = 1,
+ managedAssemblyPure = 2, // Old was: Assembly
+ managedAssemblySafe = 3,
+ managedAssemblyOldSyntax = 4
+};
+enum CompileAsOptions{
+ compileAsDefault,
+ compileAsC,
+ compileAsCPlusPlus
+};
+enum ConfigurationTypes {
+ typeUnknown = 0,
+ typeApplication = 1,
+ typeDynamicLibrary = 2,
+ typeStaticLibrary = 4,
+ typeGeneric = 10
+};
+enum debugOption {
+ debugUnknown = -1,
+ debugDisabled,
+ debugOldStyleInfo,
+ debugLineInfoOnly,
+ debugEnabled,
+ debugEditAndContinue
+};
+enum eAppProtectionOption {
+ eAppProtectUnchanged,
+ eAppProtectLow,
+ eAppProtectMedium,
+ eAppProtectHigh
+};
+enum enhancedInstructionSetOption {
+ archNotSet = 0,
+ archSSE = 1,
+ archSSE2 = 2
+};
+enum exceptionHandling {
+ ehDefault = -1,
+ ehNone = 0,
+ ehNoSEH = 1,
+ ehSEH = 2
+};
+enum enumResourceLangID {
+ rcUseDefault = 0,
+ rcAfrikaans = 1078,
+ rcAlbanian = 1052,
+ rcArabicAlgeria = 5121,
+ rcArabicBahrain = 15361,
+ rcArabicEgypt = 3073,
+ rcArabicIraq = 2049,
+ rcArabicJordan = 11265,
+ rcArabicKuwait = 13313,
+ rcArabicLebanon = 12289,
+ rcArabicLibya = 4097,
+ rcArabicMorocco = 6145,
+ rcArabicOman = 8193,
+ rcArabicQatar = 16385,
+ rcArabicSaudi = 1025,
+ rcArabicSyria = 10241,
+ rcArabicTunisia = 7169,
+ rcArabicUnitedArabEmirates = 14337,
+ rcArabicYemen = 9217,
+ rcBasque = 1069,
+ rcBulgarian = 1026,
+ rcByelorussian = 1059,
+ rcCatalan = 1027,
+ rcChineseHongKong = 3076,
+ rcChinesePRC = 2052,
+ rcChineseSingapore = 4100,
+ rcChineseTaiwan = 1028,
+ rcCroatian = 1050,
+ rcCzech = 1029,
+ rcDanish = 1030,
+ rcDutchBelgium = 2067,
+ rcDutchStandard = 1043,
+ rcEnglishAustralia = 3081,
+ rcEnglishBritain = 2057,
+ rcEnglishCanada = 4105,
+ RcEnglishCaribbean = 9225,
+ rcEnglishIreland = 6153,
+ rcEnglishJamaica = 8201,
+ rcEnglishNewZealand = 5129,
+ rcEnglishSouthAfrica = 7177,
+ rcEnglishUS = 1033,
+ rcEstonian = 1061,
+ rcFarsi = 1065,
+ rcFinnish = 1035,
+ rcFrenchBelgium = 2060,
+ rcFrenchCanada = 3084,
+ rcFrenchLuxembourg = 5132,
+ rcFrenchStandard = 1036,
+ rcFrenchSwitzerland = 4108,
+ rcGermanAustria = 3079,
+ rcGermanLichtenstein = 5127,
+ rcGermanLuxembourg = 4103,
+ rcGermanStandard = 1031,
+ rcGermanSwitzerland = 2055,
+ rcGreek = 1032,
+ rcHebrew = 1037,
+ rcHungarian = 1038,
+ rcIcelandic = 1039,
+ rcIndonesian = 1057,
+ rcItalianStandard = 1040,
+ rcItalianSwitzerland = 2064,
+ rcJapanese = 1041,
+ rcKorean = 1042,
+ rcKoreanJohab = 2066,
+ rcLatvian = 1062,
+ rcLithuanian = 1063,
+ rcNorwegianBokmal = 1044,
+ rcNorwegianNynorsk = 2068,
+ rcPolish = 1045,
+ rcPortugueseBrazilian = 1046,
+ rcPortugueseStandard = 2070,
+ rcRomanian = 1048,
+ rcRussian = 1049,
+ rcSerbian = 2074,
+ rcSlovak = 1051,
+ rcSpanishArgentina = 11274,
+ rcSpanishBolivia = 16394,
+ rcSpanishChile = 13322,
+ rcSpanishColombia = 9226,
+ rcSpanishCostaRica = 5130,
+ rcSpanishDominicanRepublic = 7178,
+ rcSpanishEcuador = 12298,
+ rcSpanishGuatemala = 4106,
+ rcSpanishMexico = 2058,
+ rcSpanishModern = 3082,
+ rcSpanishPanama = 6154,
+ rcSpanishParaguay = 15370,
+ rcSpanishPeru = 10250,
+ rcSpanishTraditional = 1034,
+ rcSpanishUruguay = 14346,
+ rcSpanishVenezuela = 8202,
+ rcSwedish = 1053,
+ rcThai = 1054,
+ rcTurkish = 1055,
+ rcUkrainian = 1058,
+ rcUrdu = 1056
+};
+enum enumSccEvent {
+ eProjectInScc,
+ ePreDirtyNotification
+};
+enum favorSizeOrSpeedOption {
+ favorNone,
+ favorSpeed,
+ favorSize
+};
+enum floatingPointModel {
+ floatingPointNotSet = -1,
+ floatingPointPrecise,
+ floatingPointStrict,
+ floatingPointFast
+};
+enum genProxyLanguage {
+ genProxyNative,
+ genProxyManaged
+};
+enum inlineExpansionOption {
+ expandDisable,
+ expandOnlyInline,
+ expandAnySuitable,
+ expandDefault // Not useful number, but stops the output
+};
+enum linkIncrementalType {
+ linkIncrementalDefault,
+ linkIncrementalNo,
+ linkIncrementalYes
+};
+enum linkProgressOption {
+ linkProgressNotSet,
+ linkProgressAll,
+ linkProgressLibs
+};
+enum machineTypeOption {
+ machineNotSet,
+ machineX86,
+ machineX64 = 17
+};
+enum midlCharOption {
+ midlCharUnsigned,
+ midlCharSigned,
+ midlCharAscii7
+};
+enum midlErrorCheckOption {
+ midlEnableCustom,
+ midlDisableAll,
+ midlEnableAll
+};
+enum midlStructMemberAlignOption {
+ midlAlignNotSet,
+ midlAlignSingleByte,
+ midlAlignTwoBytes,
+ midlAlignFourBytes,
+ midlAlignEightBytes,
+ midlAlignSixteenBytes
+};
+enum midlTargetEnvironment {
+ midlTargetNotSet,
+ midlTargetWin32,
+ midlTargetWin64
+};
+enum midlWarningLevelOption {
+ midlWarningLevel_0,
+ midlWarningLevel_1,
+ midlWarningLevel_2,
+ midlWarningLevel_3,
+ midlWarningLevel_4
+};
+enum optFoldingType {
+ optFoldingDefault,
+ optNoFolding,
+ optFolding
+};
+enum optimizeOption {
+ optimizeDisabled,
+ optimizeMinSpace,
+ optimizeMaxSpeed,
+ optimizeFull,
+ optimizeCustom,
+ optimizeDefault // Not useful number, but stops the output
+};
+enum optRefType {
+ optReferencesDefault,
+ optNoReferences,
+ optReferences
+};
+enum optWin98Type {
+ optWin98Default,
+ optWin98No,
+ optWin98Yes
+};
+enum optLinkTimeCodeGenType {
+ optLTCGDefault,
+ optLTCGEnabled,
+ optLTCGInstrument,
+ optLTCGOptimize,
+ optLTCGUpdate
+};
+enum pchOption {
+ pchUnset = -1,
+ pchNone,
+ pchCreateUsingSpecific,
+ pchGenerateAuto,
+ pchUseUsingSpecific
+};
+enum preprocessOption {
+ preprocessUnknown = -1,
+ preprocessNo,
+ preprocessYes,
+ preprocessNoLineNumbers
+};
+enum ProcessorOptimizeOption {
+ procOptimizeBlended, //GB
+ procOptimizePentium, //G5
+ procOptimizePentiumProAndAbove, //G6
+ procOptimizePentium4AndAbove //G7
+};
+enum RegisterDeployOption {
+ registerNo = 0,
+ registerYes
+};
+enum RemoteDebuggerType {
+ DbgLocal,
+ DbgRemote,
+ DbgRemoteTCPIP
+};
+enum runtimeLibraryOption {
+ rtUnknown = -1,
+ rtMultiThreaded,
+ rtMultiThreadedDebug,
+ rtMultiThreadedDLL,
+ rtMultiThreadedDebugDLL,
+ rtSingleThreaded,
+ rtSingleThreadedDebug
+};
+enum structMemberAlignOption {
+ alignNotSet,
+ alignSingleByte,
+ alignTwoBytes,
+ alignFourBytes,
+ alignEightBytes,
+ alignSixteenBytes
+};
+enum subSystemOption {
+ subSystemNotSet,
+ subSystemConsole,
+ subSystemWindows
+};
+enum termSvrAwarenessType {
+ termSvrAwareDefault,
+ termSvrAwareNo,
+ termSvrAwareYes
+};
+enum toolSetType {
+ toolSetUtility,
+ toolSetMakefile,
+ toolSetLinker,
+ toolSetLibrarian,
+ toolSetAll
+};
+enum TypeOfDebugger {
+ DbgNativeOnly,
+ DbgManagedOnly,
+ DbgMixed,
+ DbgAuto
+};
+enum useOfATL {
+ useATLNotSet,
+ useATLStatic,
+ useATLDynamic
+};
+enum useOfMfc {
+ useMfcStdWin,
+ useMfcStatic,
+ useMfcDynamic
+};
+enum useOfArchitecture {
+ archUnknown = -1,
+ archArmv4,
+ archArmv5,
+ archArmv4T,
+ archArmv5T,
+ archMips1 = 0,
+ archMips2 = 1,
+ archMips3 = 2,
+ archMips4 = 3,
+ archMips5 = 4,
+ archMips16 = 5,
+ archMips32 = 6,
+ archMips64 = 7
+};
+enum warningLevelOption {
+ warningLevelUnknown = -1,
+ warningLevel_0,
+ warningLevel_1,
+ warningLevel_2,
+ warningLevel_3,
+ warningLevel_4
+};
+
+
+class VCToolBase {
+protected:
+ // Functions
+ VCToolBase(){}
+ virtual ~VCToolBase(){}
+ virtual bool parseOption(const char* option) = 0;
+public:
+ void parseOptions(QStringList& options) {
+ for (QStringList::ConstIterator it=options.begin(); (it!=options.end()); it++)
+ parseOption((*it).toLatin1());
+ }
+ static QStringList fixCommandLine(const QString &input);
+};
+
+class VCConfiguration;
+class VCProject;
+
+class VCCLCompilerTool : public VCToolBase
+{
+public:
+ // Functions
+ VCCLCompilerTool();
+ virtual ~VCCLCompilerTool(){}
+ bool parseOption(const char* option);
+
+ // Variables
+ QStringList AdditionalIncludeDirectories;
+ QStringList AdditionalOptions;
+ QStringList AdditionalUsingDirectories;
+ QString AssemblerListingLocation;
+ asmListingOption AssemblerOutput;
+ basicRuntimeCheckOption BasicRuntimeChecks;
+ browseInfoOption BrowseInformation;
+ QString BrowseInformationFile;
+ triState BufferSecurityCheck;
+ callingConventionOption CallingConvention;
+ CompileAsOptions CompileAs;
+ compileAsManagedOptions CompileAsManaged;
+ triState CompileOnly;
+ debugOption DebugInformationFormat;
+ triState DefaultCharIsUnsigned;
+ triState Detect64BitPortabilityProblems;
+ triState DisableLanguageExtensions;
+ QStringList DisableSpecificWarnings;
+ enhancedInstructionSetOption EnableEnhancedInstructionSet;
+ triState EnableFiberSafeOptimizations;
+ triState EnableFunctionLevelLinking;
+ triState EnableIntrinsicFunctions;
+ exceptionHandling ExceptionHandling;
+ triState ExpandAttributedSource;
+ favorSizeOrSpeedOption FavorSizeOrSpeed;
+ floatingPointModel FloatingPointModel;
+ triState FloatingPointExceptions;
+ triState ForceConformanceInForLoopScope;
+ QStringList ForcedIncludeFiles;
+ QStringList ForcedUsingFiles;
+ preprocessOption GeneratePreprocessedFile;
+ triState PreprocessSuppressLineNumbers;
+ triState GlobalOptimizations;
+ triState IgnoreStandardIncludePath;
+ triState ImproveFloatingPointConsistency;
+ inlineExpansionOption InlineFunctionExpansion;
+ triState KeepComments;
+ triState MinimalRebuild;
+ QString ObjectFile;
+ triState OmitDefaultLibName;
+ triState OmitFramePointers;
+ triState OpenMP;
+ optimizeOption Optimization;
+ ProcessorOptimizeOption OptimizeForProcessor;
+ triState OptimizeForWindowsApplication;
+ QString OutputFile;
+ QString PrecompiledHeaderFile;
+ QString PrecompiledHeaderThrough;
+ QStringList PreprocessorDefinitions;
+ QString ProgramDataBaseFileName;
+ runtimeLibraryOption RuntimeLibrary;
+ triState RuntimeTypeInfo;
+ triState ShowIncludes;
+ triState SmallerTypeCheck;
+ triState StringPooling;
+ structMemberAlignOption StructMemberAlignment;
+ triState SuppressStartupBanner;
+ triState TreatWChar_tAsBuiltInType;
+ triState TurnOffAssemblyGeneration;
+ triState UndefineAllPreprocessorDefinitions;
+ QStringList UndefinePreprocessorDefinitions;
+ pchOption UsePrecompiledHeader;
+ triState UseUnicodeForAssemblerListing;
+ triState WarnAsError;
+ warningLevelOption WarningLevel;
+ triState WholeProgramOptimization;
+ useOfArchitecture CompileForArchitecture;
+ triState InterworkCalls;
+
+ // VS2010
+ triState EnablePREfast;
+ triState DisplayFullPaths;
+ triState MultiProcessorCompilation;
+ QString MultiProcessorCompilationProcessorCount;
+ triState GenerateXMLDocumentationFiles;
+ QString XMLDocumentationFileName;
+ QString ErrorReporting;
+ triState CreateHotpatchableImage;
+ QString PreprocessOutputPath;
+
+ VCConfiguration* config;
+};
+
+class VCLinkerTool : public VCToolBase
+{
+public:
+ // Functions
+ VCLinkerTool();
+ virtual ~VCLinkerTool(){}
+ bool parseOption(const char* option);
+
+ // Variables
+ QStringList AdditionalDependencies;
+ QStringList AdditionalLibraryDirectories;
+ QStringList AdditionalOptions;
+ QStringList AddModuleNamesToAssembly;
+ QString BaseAddress;
+ triState DataExecutionPrevention;
+ QStringList DelayLoadDLLs;
+ optFoldingType EnableCOMDATFolding;
+ QString EntryPointSymbol;
+ QStringList ForceSymbolReferences;
+ QString FunctionOrder;
+ triState GenerateDebugInformation;
+ triState GenerateMapFile;
+ qlonglong HeapCommitSize;
+ qlonglong HeapReserveSize;
+ triState IgnoreAllDefaultLibraries;
+ QStringList IgnoreDefaultLibraryNames;
+ triState IgnoreEmbeddedIDL;
+ triState IgnoreImportLibrary;
+ QString ImportLibrary;
+ addressAwarenessType LargeAddressAware;
+ triState LinkDLL;
+ linkIncrementalType LinkIncremental;
+ optLinkTimeCodeGenType LinkTimeCodeGeneration;
+ QString LinkToManagedResourceFile;
+ triState MapExports;
+ QString MapFileName;
+ triState MapLines;
+ QString MergedIDLBaseFileName;
+ QString MergeSections; // Should be list?
+ QString MidlCommandFile;
+ QString ModuleDefinitionFile; // Should be list?
+ optWin98Type OptimizeForWindows98;
+ optRefType OptimizeReferences;
+ QString OutputFile;
+ QString ProgramDatabaseFile;
+ triState RandomizedBaseAddress;
+ triState RegisterOutput;
+ triState ResourceOnlyDLL;
+ triState SetChecksum;
+ linkProgressOption ShowProgress;
+ qlonglong StackCommitSize;
+ qlonglong StackReserveSize;
+ QString StripPrivateSymbols; // Should be list?
+ subSystemOption SubSystem;
+ triState SupportUnloadOfDelayLoadedDLL;
+ triState SuppressStartupBanner;
+ triState SwapRunFromCD;
+ triState SwapRunFromNet;
+ machineTypeOption TargetMachine;
+ termSvrAwarenessType TerminalServerAware;
+ triState TreatWarningsAsErrors;
+ triState TurnOffAssemblyGeneration;
+ QString TypeLibraryFile;
+ qlonglong TypeLibraryResourceID;
+ QString Version;
+
+ // VS2010
+ triState GenerateManifest;
+ QStringList AdditionalManifestDependencies;
+ QString ManifestFile;
+ triState EnableUAC;
+ QString UACExecutionLevel;
+ triState UACUIAccess;
+ qlonglong SectionAlignment;
+ triState PreventDllBinding;
+ triState AllowIsolation;
+ triState AssemblyDebug;
+ QStringList AssemblyLinkResource;
+ QString CLRImageType;
+ QString CLRSupportLastError;
+ QString CLRThreadAttribute;
+ triState CLRUnmanagedCodeCheck;
+ triState DelaySign;
+ QString KeyContainer;
+ QString KeyFile;
+ QString LinkErrorReporting;
+
+ VCConfiguration* config;
+};
+
+class VCMIDLTool : public VCToolBase
+{
+public:
+ // Functions
+ VCMIDLTool();
+ virtual ~VCMIDLTool(){}
+ bool parseOption(const char* option);
+
+ // Variables
+ QStringList AdditionalIncludeDirectories;
+ QStringList AdditionalOptions;
+ QStringList CPreprocessOptions;
+ midlCharOption DefaultCharType;
+ QString DLLDataFileName; // Should be list?
+ midlErrorCheckOption EnableErrorChecks;
+ triState ErrorCheckAllocations;
+ triState ErrorCheckBounds;
+ triState ErrorCheckEnumRange;
+ triState ErrorCheckRefPointers;
+ triState ErrorCheckStubData;
+ QStringList FullIncludePath;
+ triState GenerateStublessProxies;
+ triState GenerateTypeLibrary;
+ QString HeaderFileName;
+ triState IgnoreStandardIncludePath;
+ QString InterfaceIdentifierFileName;
+ triState MkTypLibCompatible;
+ QString OutputDirectory;
+ QStringList PreprocessorDefinitions;
+ QString ProxyFileName;
+ QString RedirectOutputAndErrors;
+ midlStructMemberAlignOption StructMemberAlignment;
+ triState SuppressStartupBanner;
+ midlTargetEnvironment TargetEnvironment;
+ QString TypeLibraryName;
+ QStringList UndefinePreprocessorDefinitions;
+ triState ValidateParameters;
+ triState WarnAsError;
+ midlWarningLevelOption WarningLevel;
+
+ // VS 2010
+ triState ApplicationConfigurationMode;
+ QString GenerateClientFiles;
+ QString ClientStubFile;
+ QString TypeLibFormat;
+ triState ValidateAllParameters;
+ triState SuppressCompilerWarnings;
+ QString GenerateServerFiles;
+ QString ServerStubFile;
+ qlonglong LocaleID;
+
+ VCConfiguration* config;
+};
+
+class VCLibrarianTool : public VCToolBase
+{
+public:
+ // Functions
+ VCLibrarianTool();
+ virtual ~VCLibrarianTool(){}
+ bool parseOption(const char*){ return false; }
+
+ // Variables
+ QStringList AdditionalDependencies;
+ QStringList AdditionalLibraryDirectories;
+ QStringList AdditionalOptions;
+ QStringList ExportNamedFunctions;
+ QStringList ForceSymbolReferences;
+ triState IgnoreAllDefaultLibraries;
+ QStringList IgnoreDefaultLibraryNames;
+ QString ModuleDefinitionFile;
+ QString OutputFile;
+ triState SuppressStartupBanner;
+};
+
+class VCCustomBuildTool : public VCToolBase
+{
+public:
+ // Functions
+ VCCustomBuildTool();
+ virtual ~VCCustomBuildTool(){}
+ bool parseOption(const char*){ return false; }
+
+ // Variables
+ QStringList AdditionalDependencies;
+ QStringList CommandLine;
+ QString Description;
+ QStringList Outputs;
+ QString ToolName;
+ QString ToolPath;
+
+ VCConfiguration* config;
+};
+
+class VCResourceCompilerTool : public VCToolBase
+{
+public:
+ // Functions
+ VCResourceCompilerTool();
+ virtual ~VCResourceCompilerTool(){}
+ bool parseOption(const char*){ return false; }
+
+ // Variables
+ QStringList AdditionalIncludeDirectories;
+ QStringList AdditionalOptions;
+ enumResourceLangID Culture;
+ QStringList FullIncludePath;
+ triState IgnoreStandardIncludePath;
+ QStringList PreprocessorDefinitions;
+ QString ResourceOutputFileName;
+ linkProgressOption ShowProgress;
+ QString ToolPath;
+ triState SuppressStartupBanner;
+};
+
+class VCDeploymentTool
+{
+public:
+ // Functions
+ VCDeploymentTool();
+ virtual ~VCDeploymentTool() {}
+
+ // Variables
+ QString DeploymentTag;
+ QString RemoteDirectory;
+ RegisterDeployOption RegisterOutput;
+ QString AdditionalFiles;
+};
+
+class VCEventTool : public VCToolBase
+{
+protected:
+ // Functions
+ VCEventTool(const QString &eventName);
+ virtual ~VCEventTool(){}
+ bool parseOption(const char*){ return false; }
+
+public:
+ // Variables
+ QStringList CommandLine;
+ QString Description;
+ triState ExcludedFromBuild;
+ QString EventName;
+ QString ToolName;
+ QString ToolPath;
+};
+
+class VCPostBuildEventTool : public VCEventTool
+{
+public:
+ VCPostBuildEventTool();
+ ~VCPostBuildEventTool(){}
+};
+
+class VCPreBuildEventTool : public VCEventTool
+{
+public:
+ VCPreBuildEventTool();
+ ~VCPreBuildEventTool(){}
+};
+
+class VCPreLinkEventTool : public VCEventTool
+{
+public:
+ VCPreLinkEventTool();
+ ~VCPreLinkEventTool(){}
+};
+
+class VCConfiguration
+{
+public:
+ // Functions
+ VCConfiguration();
+ ~VCConfiguration(){}
+
+ DotNET CompilerVersion;
+
+ // Variables
+ triState ATLMinimizesCRunTimeLibraryUsage;
+ triState BuildBrowserInformation;
+ charSet CharacterSet;
+ ConfigurationTypes ConfigurationType;
+ QString DeleteExtensionsOnClean;
+ QString ImportLibrary;
+ QString IntermediateDirectory;
+ QString Name; // "ConfigurationName|PlatformName"
+ QString ConfigurationName;
+ QString OutputDirectory;
+ QString PrimaryOutput;
+ QString ProgramDatabase;
+ triState RegisterOutput;
+ useOfATL UseOfATL;
+ useOfMfc UseOfMfc;
+ triState WholeProgramOptimization;
+
+ // XML sub-parts
+ VCCLCompilerTool compiler;
+ VCLinkerTool linker;
+ VCLibrarianTool librarian;
+ VCCustomBuildTool custom;
+ VCMIDLTool idl;
+ VCPostBuildEventTool postBuild;
+ VCPreBuildEventTool preBuild;
+ VCDeploymentTool deployment;
+ VCPreLinkEventTool preLink;
+ VCResourceCompilerTool resource;
+};
+
+struct VCFilterFile
+{
+ VCFilterFile()
+ { excludeFromBuild = false; }
+ VCFilterFile(const QString &filename, bool exclude = false )
+ { file = filename; excludeFromBuild = exclude; }
+ VCFilterFile(const QString &filename, const QString &additional, bool exclude = false )
+ { file = filename; excludeFromBuild = exclude; additionalFile = additional; }
+ bool operator==(const VCFilterFile &other){
+ return file == other.file
+ && additionalFile == other.additionalFile
+ && excludeFromBuild == other.excludeFromBuild;
+ }
+
+ bool excludeFromBuild;
+ QString file;
+ QString additionalFile; // For tools like MOC
+};
+
+#ifndef QT_NO_DEBUG_OUTPUT
+inline QDebug operator<<(QDebug dbg, const VCFilterFile &p)
+{
+ dbg.nospace() << "VCFilterFile(file(" << p.file
+ << ") additionalFile(" << p.additionalFile
+ << ") excludeFromBuild(" << p.excludeFromBuild << "))" << endl;
+ return dbg.space();
+}
+#endif
+
+class VcprojGenerator;
+class VCFilter
+{
+public:
+ // Functions
+ VCFilter();
+ ~VCFilter(){}
+
+ void addFile(const QString& filename);
+ void addFile(const VCFilterFile& fileInfo);
+ void addFiles(const QStringList& fileList);
+ bool addExtraCompiler(const VCFilterFile &info);
+ void modifyPCHstage(QString str);
+
+ // Variables
+ QString Name;
+ QString Filter;
+ QString Guid;
+ triState ParseFiles;
+ VcprojGenerator* Project;
+ VCConfiguration* Config;
+ QList<VCFilterFile> Files;
+
+ customBuildCheck CustomBuild;
+
+ bool useCustomBuildTool;
+ VCCustomBuildTool CustomBuildTool;
+
+ bool useCompilerTool;
+ VCCLCompilerTool CompilerTool;
+};
+
+typedef QList<VCFilter> VCFilterList;
+class VCProjectSingleConfig
+{
+public:
+ enum FilterTypes {
+ None,
+ Source,
+ Header,
+ Generated,
+ LexYacc,
+ Translation,
+ Resources,
+ Extras
+ };
+ // Functions
+ VCProjectSingleConfig(){}
+ ~VCProjectSingleConfig(){}
+
+ // Variables
+ QString Name;
+ QString Version;
+ QString ProjectGUID;
+ QString Keyword;
+ QString SccProjectName;
+ QString SccLocalPath;
+ QString PlatformName;
+
+ // XML sub-parts
+ VCConfiguration Configuration;
+ VCFilter RootFiles;
+ VCFilter SourceFiles;
+ VCFilter HeaderFiles;
+ VCFilter GeneratedFiles;
+ VCFilter LexYaccFiles;
+ VCFilter TranslationFiles;
+ VCFilter FormFiles;
+ VCFilter ResourceFiles;
+ VCFilterList ExtraCompilersFiles;
+
+ bool flat_files;
+
+ // Accessor for extracompilers
+ VCFilter &filterForExtraCompiler(const QString &compilerName);
+};
+
+// Tree & Flat view of files --------------------------------------------------
+class VCFilter;
+class Node
+{
+public:
+ virtual ~Node() { }
+ void addElement(const VCFilterFile &file) {
+ addElement(file.file, file);
+ }
+ virtual void addElement(const QString &filepath, const VCFilterFile &allInfo) = 0;
+ virtual void removeElements()= 0;
+ virtual void generateXML(XmlOutput &xml, const QString &tagName, VCProject &tool, const QString &filter) = 0;
+ virtual bool hasElements() = 0;
+};
+
+class TreeNode : public Node
+{
+ typedef QMap<QString, TreeNode*> ChildrenMap;
+ VCFilterFile info;
+ ChildrenMap children;
+
+public:
+ virtual ~TreeNode() { removeElements(); }
+
+ int pathIndex(const QString &filepath) {
+ int Windex = filepath.indexOf("\\");
+ int Uindex = filepath.indexOf("/");
+ if (Windex != -1 && Uindex != -1)
+ return qMin(Windex, Uindex);
+ else if (Windex != -1)
+ return Windex;
+ return Uindex;
+ }
+
+ void addElement(const QString &filepath, const VCFilterFile &allInfo){
+ QString newNodeName(filepath);
+
+ int index = pathIndex(filepath);
+ if (index != -1)
+ newNodeName = filepath.left(index);
+
+ TreeNode *n = children.value(newNodeName);
+ if (!n) {
+ n = new TreeNode;
+ n->info = allInfo;
+ children.insert(newNodeName, n);
+ }
+ if (index != -1)
+ n->addElement(filepath.mid(index+1), allInfo);
+ }
+
+ void removeElements() {
+ ChildrenMap::ConstIterator it = children.constBegin();
+ ChildrenMap::ConstIterator end = children.constEnd();
+ for( ; it != end; it++) {
+ (*it)->removeElements();
+ delete it.value();
+ }
+ children.clear();
+ }
+
+ void generateXML(XmlOutput &xml, const QString &tagName, VCProject &tool, const QString &filter);
+ bool hasElements() {
+ return children.size() != 0;
+ }
+};
+
+class FlatNode : public Node
+{
+ typedef QMap<QString, VCFilterFile> ChildrenMapFlat;
+ ChildrenMapFlat children;
+
+public:
+ virtual ~FlatNode() { removeElements(); }
+
+ int pathIndex(const QString &filepath) {
+ int Windex = filepath.lastIndexOf("\\");
+ int Uindex = filepath.lastIndexOf("/");
+ if (Windex != -1 && Uindex != -1)
+ return qMax(Windex, Uindex);
+ else if (Windex != -1)
+ return Windex;
+ return Uindex;
+ }
+
+ void addElement(const QString &filepath, const VCFilterFile &allInfo){
+ QString newKey(filepath);
+
+ int index = pathIndex(filepath);
+ if (index != -1)
+ newKey = filepath.mid(index+1);
+
+ // Key designed to sort files with same
+ // name in different paths correctly
+ children.insert(newKey + "\0" + allInfo.file, allInfo);
+ }
+
+ void removeElements() {
+ children.clear();
+ }
+
+ void generateXML(XmlOutput &xml, const QString &tagName, VCProject &proj, const QString &filter);
+ bool hasElements() {
+ return children.size() != 0;
+ }
+};
+// ----------------------------------------------------------------------------
+
+class VCProject
+{
+public:
+ // Variables
+ QString Name;
+ QString Version;
+ QString ProjectGUID;
+ QString Keyword;
+ QString SccProjectName;
+ QString SccLocalPath;
+ QString PlatformName;
+
+ // Single projects
+ QList<VCProjectSingleConfig> SingleProjects;
+
+ // List of all extracompilers
+ QStringList ExtraCompilers;
+};
+
+class VCProjectWriter
+{
+public:
+ virtual ~VCProjectWriter() {}
+
+ virtual void write(XmlOutput &, VCProjectSingleConfig &);
+ virtual void write(XmlOutput &, VCProject &);
+
+ virtual void write(XmlOutput &, const VCCLCompilerTool &);
+ virtual void write(XmlOutput &, const VCLinkerTool &);
+ virtual void write(XmlOutput &, const VCMIDLTool &);
+ virtual void write(XmlOutput &, const VCCustomBuildTool &);
+ virtual void write(XmlOutput &, const VCLibrarianTool &);
+ virtual void write(XmlOutput &, const VCResourceCompilerTool &);
+ virtual void write(XmlOutput &, const VCEventTool &);
+ virtual void write(XmlOutput &, const VCDeploymentTool &);
+ virtual void write(XmlOutput &, const VCConfiguration &);
+ virtual void write(XmlOutput &, VCFilter &);
+
+private:
+ static void outputFilter(VCProject &project, XmlOutput &xml, const QString &filtername);
+ static void outputFileConfigs(VCProject &project, XmlOutput &xml, const VCFilterFile &info, const QString &filtername);
+ static void outputFileConfig(VCFilter &filter, XmlOutput &xml, const QString &filename);
+
+ friend class TreeNode;
+ friend class FlatNode;
+};
+
+QT_END_NAMESPACE
+
+#endif // MSVC_OBJECTMODEL_H
diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp
new file mode 100644
index 0000000000..56f3bfdb94
--- /dev/null
+++ b/qmake/generators/win32/msvc_vcproj.cpp
@@ -0,0 +1,1569 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the qmake application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "msvc_vcproj.h"
+#include "option.h"
+#include "xmloutput.h"
+#include <qdir.h>
+#include <qdiriterator.h>
+#include <qcryptographichash.h>
+#include <qregexp.h>
+#include <qhash.h>
+#include <quuid.h>
+#include <stdlib.h>
+
+//#define DEBUG_SOLUTION_GEN
+
+QT_BEGIN_NAMESPACE
+// Filter GUIDs (Do NOT change these!) ------------------------------
+const char _GUIDSourceFiles[] = "{4FC737F1-C7A5-4376-A066-2A32D752A2FF}";
+const char _GUIDHeaderFiles[] = "{93995380-89BD-4b04-88EB-625FBE52EBFB}";
+const char _GUIDGeneratedFiles[] = "{71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}";
+const char _GUIDResourceFiles[] = "{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}";
+const char _GUIDLexYaccFiles[] = "{E12AE0D2-192F-4d59-BD23-7D3FA58D3183}";
+const char _GUIDTranslationFiles[] = "{639EADAA-A684-42e4-A9AD-28FC9BCB8F7C}";
+const char _GUIDFormFiles[] = "{99349809-55BA-4b9d-BF79-8FDBB0286EB3}";
+const char _GUIDExtraCompilerFiles[] = "{E0D8C965-CC5F-43d7-AD63-FAEF0BBC0F85}";
+QT_END_NAMESPACE
+
+#ifdef Q_OS_WIN32
+#include <qt_windows.h>
+#include <windows/registry_p.h>
+
+QT_BEGIN_NAMESPACE
+
+struct {
+ DotNET version;
+ const char *versionStr;
+ const char *regKey;
+} dotNetCombo[] = {
+#ifdef Q_OS_WIN64
+ {NET2010, "MSVC.NET 2010 (10.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\10.0\\Setup\\VC\\ProductDir"},
+ {NET2010, "MSVC.NET 2010 Express Edition (10.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\10.0\\Setup\\VC\\ProductDir"},
+ {NET2008, "MSVC.NET 2008 (9.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\9.0\\Setup\\VC\\ProductDir"},
+ {NET2008, "MSVC.NET 2008 Express Edition (9.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\9.0\\Setup\\VC\\ProductDir"},
+ {NET2005, "MSVC.NET 2005 (8.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\ProductDir"},
+ {NET2005, "MSVC.NET 2005 Express Edition (8.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\8.0\\Setup\\VC\\ProductDir"},
+ {NET2003, "MSVC.NET 2003 (7.1)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\7.1\\Setup\\VC\\ProductDir"},
+ {NET2002, "MSVC.NET 2002 (7.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\7.0\\Setup\\VC\\ProductDir"},
+#else
+ {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"},
+#endif
+ {NETUnknown, "", ""},
+};
+
+QT_END_NAMESPACE
+#endif
+
+QT_BEGIN_NAMESPACE
+DotNET which_dotnet_version()
+{
+#ifndef Q_OS_WIN32
+ 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;
+
+ QStringList warnPath;
+ int installed = 0;
+ int i = 0;
+ for(; dotNetCombo[i].version; ++i) {
+ QString path = qt_readRegistryKey(HKEY_LOCAL_MACHINE, dotNetCombo[i].regKey);
+ if(!path.isEmpty()) {
+ ++installed;
+ current_version = dotNetCombo[i].version;
+ warnPath += QString("%1").arg(dotNetCombo[i].versionStr);
+ }
+ }
+
+ if (installed < 2)
+ return current_version;
+
+ // More than one version installed, search directory path
+ QString paths = qgetenv("PATH");
+ QStringList pathlist = paths.toLower().split(";");
+
+ i = installed = 0;
+ for(; dotNetCombo[i].version; ++i) {
+ QString productPath = qt_readRegistryKey(HKEY_LOCAL_MACHINE, dotNetCombo[i].regKey).toLower();
+ if (productPath.isEmpty())
+ continue;
+ QStringList::iterator it;
+ for(it = pathlist.begin(); it != pathlist.end(); ++it) {
+ if((*it).contains(productPath)) {
+ ++installed;
+ current_version = dotNetCombo[i].version;
+ warnPath += QString("%1 in path").arg(dotNetCombo[i].versionStr);
+ break;
+ }
+ }
+ }
+ switch(installed) {
+ case 1:
+ break;
+ case 0:
+ warn_msg(WarnLogic, "Generator: MSVC.NET: Found more than one version of Visual Studio, but"
+ " none in your path! Fallback to lowest version (%s)", warnPath.join(", ").toLatin1().data());
+ break;
+ default:
+ warn_msg(WarnLogic, "Generator: MSVC.NET: Found more than one version of Visual Studio in"
+ " your path! Fallback to lowest version (%s)", warnPath.join(", ").toLatin1().data());
+ break;
+ }
+
+ return current_version;
+#endif
+};
+
+// Flatfile Tags ----------------------------------------------------
+const char _slnHeader70[] = "Microsoft Visual Studio Solution File, Format Version 7.00";
+const char _slnHeader71[] = "Microsoft Visual Studio Solution File, Format Version 8.00";
+const char _slnHeader80[] = "Microsoft Visual Studio Solution File, Format Version 9.00"
+ "\n# Visual Studio 2005";
+const char _slnHeader90[] = "Microsoft Visual Studio Solution File, Format Version 10.00"
+ "\n# Visual Studio 2008";
+const char _slnHeader100[] = "Microsoft Visual Studio Solution File, Format Version 11.00"
+ "\n# Visual Studio 2010";
+ // The following UUID _may_ change for later servicepacks...
+ // If so we need to search through the registry at
+ // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\7.0\Projects
+ // to find the subkey that contains a "PossibleProjectExtension"
+ // containing "vcproj"...
+ // Use the hardcoded value for now so projects generated on other
+ // platforms are actually usable.
+const char _slnMSVCvcprojGUID[] = "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}";
+const char _slnProjectBeg[] = "\nProject(\"";
+const char _slnProjectMid[] = "\") = ";
+const char _slnProjectEnd[] = "\nEndProject";
+const char _slnGlobalBeg[] = "\nGlobal";
+const char _slnGlobalEnd[] = "\nEndGlobal";
+const char _slnSolutionConf[] = "\n\tGlobalSection(SolutionConfiguration) = preSolution"
+ "\n\t\tConfigName.0 = Debug|Win32"
+ "\n\t\tConfigName.1 = Release|Win32"
+ "\n\tEndGlobalSection";
+const char _slnProjDepBeg[] = "\n\tGlobalSection(ProjectDependencies) = postSolution";
+const char _slnProjDepEnd[] = "\n\tEndGlobalSection";
+const char _slnProjConfBeg[] = "\n\tGlobalSection(ProjectConfiguration) = postSolution";
+const char _slnProjRelConfTag1[]= ".Release|%1.ActiveCfg = Release|";
+const char _slnProjRelConfTag2[]= ".Release|%1.Build.0 = Release|";
+const char _slnProjDbgConfTag1[]= ".Debug|%1.ActiveCfg = Debug|";
+const char _slnProjDbgConfTag2[]= ".Debug|%1.Build.0 = Debug|";
+const char _slnProjConfEnd[] = "\n\tEndGlobalSection";
+const char _slnExtSections[] = "\n\tGlobalSection(ExtensibilityGlobals) = postSolution"
+ "\n\tEndGlobalSection"
+ "\n\tGlobalSection(ExtensibilityAddIns) = postSolution"
+ "\n\tEndGlobalSection";
+// ------------------------------------------------------------------
+
+VcprojGenerator::VcprojGenerator()
+ : Win32MakefileGenerator(),
+ init_flag(false),
+ projectWriter(0)
+{
+}
+
+VcprojGenerator::~VcprojGenerator()
+{
+ delete projectWriter;
+}
+
+bool VcprojGenerator::writeMakefile(QTextStream &t)
+{
+ initProject(); // Fills the whole project with proper data
+
+ // Generate solution file
+ if(project->first("TEMPLATE") == "vcsubdirs") {
+ if (!project->isActiveConfig("build_pass")) {
+ debug_msg(1, "Generator: MSVC.NET: Writing solution file");
+ writeSubDirs(t);
+ } else {
+ debug_msg(1, "Generator: MSVC.NET: Not writing solution file for build_pass configs");
+ }
+ return true;
+ } else
+ // Generate single configuration project file
+ if (project->first("TEMPLATE") == "vcapp" ||
+ project->first("TEMPLATE") == "vclib") {
+ if(!project->isActiveConfig("build_pass")) {
+ debug_msg(1, "Generator: MSVC.NET: Writing single configuration project file");
+ XmlOutput xmlOut(t);
+ projectWriter->write(xmlOut, vcProject);
+ }
+ return true;
+ }
+ return project->isActiveConfig("build_pass");
+}
+
+bool VcprojGenerator::writeProjectMakefile()
+{
+ usePlatformDir();
+ QTextStream t(&Option::output);
+
+ // Check if all requirements are fulfilled
+ if(!project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty()) {
+ fprintf(stderr, "Project file not generated because all requirements not met:\n\t%s\n",
+ var("QMAKE_FAILED_REQUIREMENTS").toLatin1().constData());
+ return true;
+ }
+
+ // Generate project file
+ if(project->first("TEMPLATE") == "vcapp" ||
+ project->first("TEMPLATE") == "vclib") {
+ if (!mergedProjects.count()) {
+ warn_msg(WarnLogic, "Generator: MSVC.NET: no single configuration created, cannot output project!");
+ return false;
+ }
+
+ debug_msg(1, "Generator: MSVC.NET: Writing project file");
+ VCProject mergedProject;
+ for (int i = 0; i < mergedProjects.count(); ++i) {
+ VCProjectSingleConfig *singleProject = &(mergedProjects.at(i)->vcProject);
+ mergedProject.SingleProjects += *singleProject;
+ for (int j = 0; j < singleProject->ExtraCompilersFiles.count(); ++j) {
+ const QString &compilerName = singleProject->ExtraCompilersFiles.at(j).Name;
+ if (!mergedProject.ExtraCompilers.contains(compilerName))
+ mergedProject.ExtraCompilers += compilerName;
+ }
+ }
+
+ if(mergedProjects.count() > 1 &&
+ mergedProjects.at(0)->vcProject.Name ==
+ mergedProjects.at(1)->vcProject.Name)
+ mergedProjects.at(0)->writePrlFile();
+ mergedProject.Name = project->first("QMAKE_PROJECT_NAME");
+ mergedProject.Version = mergedProjects.at(0)->vcProject.Version;
+ mergedProject.ProjectGUID = project->isEmpty("QMAKE_UUID") ? getProjectUUID().toString().toUpper() : project->first("QMAKE_UUID");
+ mergedProject.Keyword = project->first("VCPROJ_KEYWORD");
+ mergedProject.SccProjectName = mergedProjects.at(0)->vcProject.SccProjectName;
+ mergedProject.SccLocalPath = mergedProjects.at(0)->vcProject.SccLocalPath;
+ mergedProject.PlatformName = mergedProjects.at(0)->vcProject.PlatformName;
+
+ XmlOutput xmlOut(t);
+ projectWriter->write(xmlOut, mergedProject);
+ return true;
+ } else if(project->first("TEMPLATE") == "vcsubdirs") {
+ return writeMakefile(t);
+ }
+ return false;
+}
+
+struct VcsolutionDepend {
+ QString uuid;
+ QString vcprojFile, orig_target, target;
+ Target targetType;
+ QStringList dependencies;
+};
+
+QUuid VcprojGenerator::getProjectUUID(const QString &filename)
+{
+ bool validUUID = true;
+
+ // Read GUID from variable-space
+ QUuid uuid = project->first("GUID");
+
+ // If none, create one based on the MD5 of absolute project path
+ if(uuid.isNull() || !filename.isEmpty()) {
+ QString abspath = Option::fixPathToLocalOS(filename.isEmpty()?project->first("QMAKE_MAKEFILE"):filename);
+ QByteArray digest = QCryptographicHash::hash(abspath.toUtf8(), QCryptographicHash::Md5);
+ memcpy((unsigned char*)(&uuid), digest.constData(), sizeof(QUuid));
+ validUUID = !uuid.isNull();
+ uuid.data4[0] = (uuid.data4[0] & 0x3F) | 0x80; // UV_DCE variant
+ uuid.data3 = (uuid.data3 & 0x0FFF) | (QUuid::Name<<12);
+ }
+
+ // If still not valid, generate new one, and suggest adding to .pro
+ if(uuid.isNull() || !validUUID) {
+ uuid = QUuid::createUuid();
+ fprintf(stderr,
+ "qmake couldn't create a GUID based on filepath, and we couldn't\nfind a valid GUID in the .pro file (Consider adding\n'GUID = %s' to the .pro file)\n",
+ uuid.toString().toUpper().toLatin1().constData());
+ }
+
+ // Store GUID in variable-space
+ project->values("GUID") = QStringList(uuid.toString().toUpper());
+ return uuid;
+}
+
+QUuid VcprojGenerator::increaseUUID(const QUuid &id)
+{
+ QUuid result(id);
+ qint64 dataFirst = (result.data4[0] << 24) +
+ (result.data4[1] << 16) +
+ (result.data4[2] << 8) +
+ result.data4[3];
+ qint64 dataLast = (result.data4[4] << 24) +
+ (result.data4[5] << 16) +
+ (result.data4[6] << 8) +
+ result.data4[7];
+
+ if(!(dataLast++))
+ dataFirst++;
+
+ result.data4[0] = uchar((dataFirst >> 24) & 0xff);
+ result.data4[1] = uchar((dataFirst >> 16) & 0xff);
+ result.data4[2] = uchar((dataFirst >> 8) & 0xff);
+ result.data4[3] = uchar(dataFirst & 0xff);
+ result.data4[4] = uchar((dataLast >> 24) & 0xff);
+ result.data4[5] = uchar((dataLast >> 16) & 0xff);
+ result.data4[6] = uchar((dataLast >> 8) & 0xff);
+ result.data4[7] = uchar(dataLast & 0xff);
+ return result;
+}
+
+QStringList VcprojGenerator::collectSubDirs(QMakeProject *proj)
+{
+ QStringList subdirs;
+ QStringList tmp_proj_subdirs = proj->variables()["SUBDIRS"];
+ for(int x = 0; x < tmp_proj_subdirs.size(); ++x) {
+ QString tmpdir = tmp_proj_subdirs.at(x);
+ if(!proj->isEmpty(tmpdir + ".file")) {
+ if(!proj->isEmpty(tmpdir + ".subdir"))
+ warn_msg(WarnLogic, "Cannot assign both file and subdir for subdir %s",
+ tmpdir.toLatin1().constData());
+ tmpdir = proj->first(tmpdir + ".file");
+ } else if(!proj->isEmpty(tmpdir + ".subdir")) {
+ tmpdir = proj->first(tmpdir + ".subdir");
+ }
+ subdirs += tmpdir;
+ }
+ return subdirs;
+}
+
+void VcprojGenerator::writeSubDirs(QTextStream &t)
+{
+ // Check if all requirements are fulfilled
+ if(!project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty()) {
+ fprintf(stderr, "Project file not generated because all requirements not met:\n\t%s\n",
+ var("QMAKE_FAILED_REQUIREMENTS").toLatin1().constData());
+ return;
+ }
+
+ switch(which_dotnet_version()) {
+ case NET2010:
+ t << _slnHeader100;
+ break;
+ case NET2008:
+ t << _slnHeader90;
+ break;
+ case NET2005:
+ t << _slnHeader80;
+ break;
+ case NET2003:
+ t << _slnHeader71;
+ break;
+ case NET2002:
+ t << _slnHeader70;
+ break;
+ default:
+ t << _slnHeader70;
+ warn_msg(WarnLogic, "Generator: MSVC.NET: Unknown version (%d) of MSVC detected for .sln", which_dotnet_version());
+ break;
+ }
+
+ QHash<QString, VcsolutionDepend*> solution_depends;
+ QList<VcsolutionDepend*> solution_cleanup;
+
+ QString oldpwd = qmake_getpwd();
+
+ // Make sure that all temp projects are configured
+ // for release so that the depends are created
+ // without the debug <lib>dxxx.lib name mangling
+ QStringList old_after_vars = Option::after_user_vars;
+ Option::after_user_vars.append("CONFIG+=release");
+
+ QStringList subdirs = collectSubDirs(project);
+ for(int i = 0; i < subdirs.size(); ++i) {
+ QString tmp = subdirs.at(i);
+ QFileInfo fi(fileInfo(Option::fixPathToLocalOS(tmp, true)));
+ if(fi.exists()) {
+ if(fi.isDir()) {
+ QString profile = tmp;
+ if(!profile.endsWith(Option::dir_sep))
+ profile += Option::dir_sep;
+ profile += fi.baseName() + Option::pro_ext;
+ subdirs.append(profile);
+ } else {
+ QMakeProject tmp_proj;
+ QString dir = fi.path(), fn = fi.fileName();
+ if(!dir.isEmpty()) {
+ if(!qmake_setpwd(dir))
+ fprintf(stderr, "Cannot find directory: %s\n", dir.toLatin1().constData());
+ }
+ if(tmp_proj.read(fn)) {
+ // Check if all requirements are fulfilled
+ if(!tmp_proj.variables()["QMAKE_FAILED_REQUIREMENTS"].isEmpty()) {
+ fprintf(stderr, "Project file(%s) not added to Solution because all requirements not met:\n\t%s\n",
+ fn.toLatin1().constData(), tmp_proj.values("QMAKE_FAILED_REQUIREMENTS").join(" ").toLatin1().constData());
+ continue;
+ }
+ if(tmp_proj.first("TEMPLATE") == "vcsubdirs") {
+ foreach(const QString &tmpdir, collectSubDirs(&tmp_proj))
+ subdirs += fileFixify(tmpdir);
+ } else if(tmp_proj.first("TEMPLATE") == "vcapp" || tmp_proj.first("TEMPLATE") == "vclib") {
+ // Initialize a 'fake' project to get the correct variables
+ // and to be able to extract all the dependencies
+ Option::QMAKE_MODE old_mode = Option::qmake_mode;
+ Option::qmake_mode = Option::QMAKE_GENERATE_NOTHING;
+ VcprojGenerator tmp_vcproj;
+ tmp_vcproj.setNoIO(true);
+ tmp_vcproj.setProjectFile(&tmp_proj);
+ Option::qmake_mode = old_mode;
+ if(Option::debug_level) {
+ debug_msg(1, "Dumping all variables:");
+ QMap<QString, QStringList> &vars = tmp_proj.variables();
+ for(QMap<QString, QStringList>::Iterator it = vars.begin();
+ it != vars.end(); ++it) {
+ if(it.key().left(1) != "." && !it.value().isEmpty())
+ debug_msg(1, "%s: %s === %s", fn.toLatin1().constData(), it.key().toLatin1().constData(),
+ it.value().join(" :: ").toLatin1().constData());
+ }
+ }
+
+ // We assume project filename is [QMAKE_PROJECT_NAME].vcproj
+ QString vcproj = unescapeFilePath(tmp_vcproj.project->first("QMAKE_PROJECT_NAME") + project->first("VCPROJ_EXTENSION"));
+ QString vcprojDir = qmake_getpwd();
+
+ // If file doesn't exsist, then maybe the users configuration
+ // doesn't allow it to be created. Skip to next...
+ if(!exists(vcprojDir + Option::dir_sep + vcproj)) {
+
+ // Try to find the directory which fits relative
+ // to the output path, which represents the shadow
+ // path in case we are shadow building
+ QStringList list = fi.path().split(QLatin1Char('/'));
+ QString tmpDir = QFileInfo(Option::output).path() + Option::dir_sep;
+ bool found = false;
+ for (int i = list.size() - 1; i >= 0; --i) {
+ QString curr;
+ for (int j = i; j < list.size(); ++j)
+ curr += list.at(j) + Option::dir_sep;
+ if (exists(tmpDir + curr + vcproj)) {
+ vcprojDir = QDir::cleanPath(tmpDir + curr);
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ warn_msg(WarnLogic, "Ignored (not found) '%s'", QString(vcprojDir + Option::dir_sep + vcproj).toLatin1().constData());
+ goto nextfile; // # Dirty!
+ }
+ }
+
+ VcsolutionDepend *newDep = new VcsolutionDepend;
+ newDep->vcprojFile = vcprojDir + Option::dir_sep + vcproj;
+ newDep->orig_target = unescapeFilePath(tmp_proj.first("QMAKE_ORIG_TARGET"));
+ newDep->target = tmp_proj.first("MSVCPROJ_TARGET").section(Option::dir_sep, -1);
+ newDep->targetType = tmp_vcproj.projectTarget;
+ newDep->uuid = tmp_proj.isEmpty("QMAKE_UUID") ? getProjectUUID(Option::fixPathToLocalOS(vcprojDir + QDir::separator() + vcproj)).toString().toUpper(): tmp_proj.first("QMAKE_UUID");
+
+ // We want to store it as the .lib name.
+ if(newDep->target.endsWith(".dll"))
+ newDep->target = newDep->target.left(newDep->target.length()-3) + "lib";
+
+ // All ActiveQt Server projects are dependent on idc.exe
+ if(tmp_proj.variables()["CONFIG"].contains("qaxserver"))
+ newDep->dependencies << "idc.exe";
+
+ // All extra compilers which has valid input are considered dependencies
+ const QStringList &quc = tmp_proj.variables()["QMAKE_EXTRA_COMPILERS"];
+ for(QStringList::ConstIterator it = quc.constBegin(); it != quc.constEnd(); ++it) {
+ const QStringList &invar = tmp_proj.variables().value((*it) + ".input");
+ for(QStringList::ConstIterator iit = invar.constBegin(); iit != invar.constEnd(); ++iit) {
+ const QStringList fileList = tmp_proj.variables().value(*iit);
+ if (!fileList.isEmpty()) {
+ const QStringList &cmdsParts = tmp_proj.variables().value((*it) + ".commands");
+ bool startOfLine = true;
+ foreach(QString cmd, cmdsParts) {
+ if (!startOfLine) {
+ if (cmd.contains("\r"))
+ startOfLine = true;
+ continue;
+ }
+ if (cmd.isEmpty())
+ continue;
+
+ startOfLine = false;
+ // Extra compiler commands might be defined in variables, so
+ // expand them (don't care about the in/out files)
+ cmd = tmp_vcproj.replaceExtraCompilerVariables(cmd, QStringList(), QStringList());
+ // Pull out command based on spaces and quoting, if the
+ // command starts with that
+ cmd = cmd.left(cmd.indexOf(cmd.at(0) == '"' ? '"' : ' ', 1));
+ QString dep = cmd.section('/', -1).section('\\', -1);
+ if (!newDep->dependencies.contains(dep))
+ newDep->dependencies << dep;
+ }
+ }
+ }
+ }
+
+ // Add all unknown libs to the deps
+ QStringList where = QStringList() << "QMAKE_LIBS" << "QMAKE_LIBS_PRIVATE";
+ if(!tmp_proj.isEmpty("QMAKE_INTERNAL_PRL_LIBS"))
+ where = tmp_proj.variables()["QMAKE_INTERNAL_PRL_LIBS"];
+ for(QStringList::iterator wit = where.begin();
+ wit != where.end(); ++wit) {
+ QStringList &l = tmp_proj.variables()[(*wit)];
+ for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
+ QString opt = (*it);
+ if(!opt.startsWith("/") && // Not a switch
+ opt != newDep->target && // Not self
+ opt != "opengl32.lib" && // We don't care about these libs
+ opt != "glu32.lib" && // to make depgen alittle faster
+ opt != "kernel32.lib" &&
+ opt != "user32.lib" &&
+ opt != "gdi32.lib" &&
+ opt != "comdlg32.lib" &&
+ opt != "advapi32.lib" &&
+ opt != "shell32.lib" &&
+ opt != "ole32.lib" &&
+ opt != "oleaut32.lib" &&
+ opt != "uuid.lib" &&
+ opt != "imm32.lib" &&
+ opt != "winmm.lib" &&
+ opt != "wsock32.lib" &&
+ opt != "ws2_32.lib" &&
+ opt != "winspool.lib" &&
+ opt != "delayimp.lib")
+ {
+ newDep->dependencies << opt.section(Option::dir_sep, -1);
+ }
+ }
+ }
+#ifdef DEBUG_SOLUTION_GEN
+ qDebug("Deps for %20s: [%s]", newDep->target.toLatin1().constData(), newDep->dependencies.join(" :: ").toLatin1().constData());
+#endif
+ solution_cleanup.append(newDep);
+ solution_depends.insert(newDep->target, newDep);
+ t << _slnProjectBeg << _slnMSVCvcprojGUID << _slnProjectMid
+ << "\"" << newDep->orig_target << "\", \"" << newDep->vcprojFile
+ << "\", \"" << newDep->uuid << "\"";
+ t << _slnProjectEnd;
+ }
+ }
+nextfile:
+ qmake_setpwd(oldpwd);
+ }
+ }
+ }
+ t << _slnGlobalBeg;
+ if (!project->isEmpty("CE_SDK") && !project->isEmpty("CE_ARCH")) {
+ QString slnConfCE = _slnSolutionConf;
+ QString platform = QString("|") + project->values("CE_SDK").join(" ") + " (" + project->first("CE_ARCH") + ")";
+ slnConfCE.replace(QString("|Win32"), platform);
+ t << slnConfCE;
+ } else {
+ t << _slnSolutionConf;
+ }
+ t << _slnProjDepBeg;
+
+ // Restore previous after_user_var options
+ Option::after_user_vars = old_after_vars;
+
+ // Figure out dependencies
+ for(QList<VcsolutionDepend*>::Iterator it = solution_cleanup.begin(); it != solution_cleanup.end(); ++it) {
+ int cnt = 0;
+ for(QStringList::iterator dit = (*it)->dependencies.begin(); dit != (*it)->dependencies.end(); ++dit) {
+ if(VcsolutionDepend *vc = solution_depends[*dit])
+ t << "\n\t\t" << (*it)->uuid << "." << cnt++ << " = " << vc->uuid;
+ }
+ }
+ t << _slnProjDepEnd;
+ t << _slnProjConfBeg;
+ for(QList<VcsolutionDepend*>::Iterator it = solution_cleanup.begin(); it != solution_cleanup.end(); ++it) {
+ QString platform = "Win32";
+ if (!project->isEmpty("CE_SDK") && !project->isEmpty("CE_ARCH"))
+ platform = project->values("CE_SDK").join(" ") + " (" + project->first("CE_ARCH") + ")";
+ t << "\n\t\t" << (*it)->uuid << QString(_slnProjDbgConfTag1).arg(platform) << platform;
+ t << "\n\t\t" << (*it)->uuid << QString(_slnProjDbgConfTag2).arg(platform) << platform;
+ t << "\n\t\t" << (*it)->uuid << QString(_slnProjRelConfTag1).arg(platform) << platform;
+ t << "\n\t\t" << (*it)->uuid << QString(_slnProjRelConfTag2).arg(platform) << platform;
+ }
+ t << _slnProjConfEnd;
+ t << _slnExtSections;
+ t << _slnGlobalEnd;
+
+
+ while (!solution_cleanup.isEmpty())
+ delete solution_cleanup.takeFirst();
+}
+
+// ------------------------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------------------------
+
+bool VcprojGenerator::hasBuiltinCompiler(const QString &file)
+{
+ // Source files
+ for (int i = 0; i < Option::cpp_ext.count(); ++i)
+ if (file.endsWith(Option::cpp_ext.at(i)))
+ return true;
+ for (int i = 0; i < Option::c_ext.count(); ++i)
+ if (file.endsWith(Option::c_ext.at(i)))
+ return true;
+ if (file.endsWith(".rc")
+ || file.endsWith(".idl"))
+ return true;
+ return false;
+}
+
+void VcprojGenerator::init()
+{
+ if (init_flag)
+ return;
+ init_flag = true;
+ projectWriter = createProjectWriter();
+
+ if(project->first("TEMPLATE") == "vcsubdirs") //too much work for subdirs
+ return;
+
+ debug_msg(1, "Generator: MSVC.NET: Initializing variables");
+
+ // this should probably not be here, but I'm using it to wrap the .t files
+ if (project->first("TEMPLATE") == "vcapp")
+ project->values("QMAKE_APP_FLAG").append("1");
+ else if (project->first("TEMPLATE") == "vclib")
+ project->values("QMAKE_LIB_FLAG").append("1");
+ if (project->values("QMAKESPEC").isEmpty())
+ project->values("QMAKESPEC").append(qgetenv("QMAKESPEC"));
+
+ processVars();
+
+ project->values("QMAKE_LIBS") += escapeFilePaths(project->values("LIBS"));
+ project->values("QMAKE_LIBS_PRIVATE") += escapeFilePaths(project->values("LIBS_PRIVATE"));
+
+ if(!project->values("VERSION").isEmpty()) {
+ QString version = project->values("VERSION")[0];
+ int firstDot = version.indexOf(".");
+ QString major = version.left(firstDot);
+ QString minor = version.right(version.length() - firstDot - 1);
+ minor.replace(QRegExp("\\."), "");
+ project->values("QMAKE_LFLAGS").append("/VERSION:" + major + "." + minor);
+ }
+
+ MakefileGenerator::init();
+ initOld(); // Currently calling old DSP code to set variables. CLEAN UP!
+
+ // Figure out what we're trying to build
+ if(project->first("TEMPLATE") == "vcapp") {
+ projectTarget = Application;
+ } else if(project->first("TEMPLATE") == "vclib") {
+ if(project->isActiveConfig("staticlib")) {
+ if (!project->values("RES_FILE").isEmpty())
+ project->values("MSVCPROJ_LIBS") += escapeFilePaths(project->values("RES_FILE"));
+ projectTarget = StaticLib;
+ } else
+ projectTarget = SharedLib;
+ }
+
+ // Setup PCH variables
+ precompH = project->first("PRECOMPILED_HEADER");
+ precompCPP = project->first("PRECOMPILED_SOURCE");
+ usePCH = !precompH.isEmpty() && project->isActiveConfig("precompile_header");
+ if (usePCH) {
+ precompHFilename = fileInfo(precompH).fileName();
+ // Created files
+ QString origTarget = unescapeFilePath(project->first("QMAKE_ORIG_TARGET"));
+ precompObj = origTarget + Option::obj_ext;
+ precompPch = origTarget + ".pch";
+ // Add PRECOMPILED_HEADER to HEADERS
+ if (!project->values("HEADERS").contains(precompH))
+ project->values("HEADERS") += precompH;
+ // Return to variable pool
+ project->values("PRECOMPILED_OBJECT") = QStringList(precompObj);
+ project->values("PRECOMPILED_PCH") = QStringList(precompPch);
+
+ autogenPrecompCPP = precompCPP.isEmpty() && project->isActiveConfig("autogen_precompile_source");
+ if (autogenPrecompCPP) {
+ precompCPP = precompH
+ + (Option::cpp_ext.count() ? Option::cpp_ext.at(0) : QLatin1String(".cpp"));
+ project->values("GENERATED_SOURCES") += precompCPP;
+ } else if (!precompCPP.isEmpty()) {
+ project->values("SOURCES") += precompCPP;
+ }
+ }
+
+ // Add all input files for a custom compiler into a map for uniqueness,
+ // unless the compiler is configure as a combined stage, then use the first one
+ const QStringList &quc = project->values("QMAKE_EXTRA_COMPILERS");
+ for(QStringList::ConstIterator it = quc.constBegin(); it != quc.constEnd(); ++it) {
+ const QStringList &invar = project->variables().value((*it) + ".input");
+ const QString compiler_out = project->first((*it) + ".output");
+ for(QStringList::ConstIterator iit = invar.constBegin(); iit != invar.constEnd(); ++iit) {
+ QStringList fileList = project->variables().value(*iit);
+ if (!fileList.isEmpty()) {
+ if (project->values((*it) + ".CONFIG").indexOf("combine") != -1)
+ fileList = QStringList(fileList.first());
+ for(QStringList::ConstIterator fit = fileList.constBegin(); fit != fileList.constEnd(); ++fit) {
+ QString file = (*fit);
+ if (verifyExtraCompiler((*it), file)) {
+ if (!hasBuiltinCompiler(file)) {
+ extraCompilerSources[file] += *it;
+ } else {
+ QString out = Option::fixPathToTargetOS(replaceExtraCompilerVariables(
+ compiler_out, file, QString()), false);
+ extraCompilerSources[out] += *it;
+ extraCompilerOutputs[out] = QStringList(file); // Can only have one
+ }
+ }
+ }
+ }
+ }
+ }
+
+#if 0 // Debugging
+ Q_FOREACH(QString aKey, extraCompilerSources.keys()) {
+ qDebug("Extracompilers for %s are (%s)", aKey.toLatin1().constData(), extraCompilerSources.value(aKey).join(", ").toLatin1().constData());
+ }
+ Q_FOREACH(QString aKey, extraCompilerOutputs.keys()) {
+ qDebug("Object mapping for %s is (%s)", aKey.toLatin1().constData(), extraCompilerOutputs.value(aKey).join(", ").toLatin1().constData());
+ }
+ qDebug("");
+#endif
+}
+
+bool VcprojGenerator::mergeBuildProject(MakefileGenerator *other)
+{
+ if (!other || !other->projectFile()) {
+ warn_msg(WarnLogic, "VcprojGenerator: Cannot merge null project.");
+ return false;
+ }
+ if (other->projectFile()->first("MAKEFILE_GENERATOR") != project->first("MAKEFILE_GENERATOR")) {
+ warn_msg(WarnLogic, "VcprojGenerator: Cannot merge other types of projects! (ignored)");
+ return false;
+ }
+
+ VcprojGenerator *otherVC = static_cast<VcprojGenerator*>(other);
+ mergedProjects += otherVC;
+ return true;
+}
+
+void VcprojGenerator::initProject()
+{
+ // Initialize XML sub elements
+ // - Do this first since project elements may need
+ // - to know of certain configuration options
+ initConfiguration();
+ initRootFiles();
+ initSourceFiles();
+ initHeaderFiles();
+ initGeneratedFiles();
+ initLexYaccFiles();
+ initTranslationFiles();
+ initFormFiles();
+ initResourceFiles();
+ initExtraCompilerOutputs();
+
+ // Own elements -----------------------------
+ vcProject.Name = unescapeFilePath(project->first("QMAKE_ORIG_TARGET"));
+ switch(which_dotnet_version()) {
+ case NET2010:
+ vcProject.Version = "10.00";
+ break;
+ case NET2008:
+ vcProject.Version = "9,00";
+ break;
+ case NET2005:
+ //### using ',' because of a bug in 2005 B2
+ //### VS uses '.' or ',' depending on the regional settings! Using ',' always works.
+ vcProject.Version = "8,00";
+ break;
+ case NET2003:
+ vcProject.Version = "7.10";
+ break;
+ case NET2002:
+ vcProject.Version = "7.00";
+ break;
+ default:
+ vcProject.Version = "7.00";
+ warn_msg(WarnLogic, "Generator: MSVC.NET: Unknown version (%d) of MSVC detected for .vcproj", which_dotnet_version());
+ break;
+ }
+
+ vcProject.Keyword = project->first("VCPROJ_KEYWORD");
+ if (project->isEmpty("CE_SDK") || project->isEmpty("CE_ARCH")) {
+ vcProject.PlatformName = (vcProject.Configuration.idl.TargetEnvironment == midlTargetWin64 ? "Win64" : "Win32");
+ } else {
+ vcProject.PlatformName = project->values("CE_SDK").join(" ") + " (" + project->first("CE_ARCH") + ")";
+ }
+ // These are not used by Qt, but may be used by customers
+ vcProject.SccProjectName = project->first("SCCPROJECTNAME");
+ vcProject.SccLocalPath = project->first("SCCLOCALPATH");
+ vcProject.flat_files = project->isActiveConfig("flat");
+}
+
+void VcprojGenerator::initConfiguration()
+{
+ // Initialize XML sub elements
+ // - Do this first since main configuration elements may need
+ // - to know of certain compiler/linker options
+ VCConfiguration &conf = vcProject.Configuration;
+ conf.CompilerVersion = which_dotnet_version();
+
+ initCompilerTool();
+
+ // Only on configuration per build
+ bool isDebug = project->isActiveConfig("debug");
+
+ if(projectTarget == StaticLib)
+ initLibrarianTool();
+ else {
+ conf.linker.GenerateDebugInformation = isDebug ? _True : _False;
+ initLinkerTool();
+ }
+ initResourceTool();
+ initIDLTool();
+
+ // Own elements -----------------------------
+ QString temp = project->first("BuildBrowserInformation");
+ switch (projectTarget) {
+ case SharedLib:
+ conf.ConfigurationType = typeDynamicLibrary;
+ break;
+ case StaticLib:
+ conf.ConfigurationType = typeStaticLibrary;
+ break;
+ case Application:
+ default:
+ conf.ConfigurationType = typeApplication;
+ break;
+ }
+
+ conf.OutputDirectory = project->first("DESTDIR");
+ if (conf.OutputDirectory.isEmpty())
+ conf.OutputDirectory = ".\\";
+ if (!conf.OutputDirectory.endsWith("\\"))
+ conf.OutputDirectory += '\\';
+ if (conf.CompilerVersion >= NET2010) {
+ // The target name could have been changed.
+ conf.PrimaryOutput = project->first("TARGET");
+ if ( !conf.PrimaryOutput.isEmpty() && !project->first("TARGET_VERSION_EXT").isEmpty() && project->isActiveConfig("shared"))
+ conf.PrimaryOutput.append(project->first("TARGET_VERSION_EXT"));
+ }
+
+ conf.Name = project->values("BUILD_NAME").join(" ");
+ if (conf.Name.isEmpty())
+ conf.Name = isDebug ? "Debug" : "Release";
+ conf.ConfigurationName = conf.Name;
+ if (project->isEmpty("CE_SDK") || project->isEmpty("CE_ARCH")) {
+ conf.Name += (conf.idl.TargetEnvironment == midlTargetWin64 ? "|Win64" : "|Win32");
+ } else {
+ conf.Name += "|" + project->values("CE_SDK").join(" ") + " (" + project->first("CE_ARCH") + ")";
+ }
+ conf.ATLMinimizesCRunTimeLibraryUsage = (project->first("ATLMinimizesCRunTimeLibraryUsage").isEmpty() ? _False : _True);
+ conf.BuildBrowserInformation = triState(temp.isEmpty() ? (short)unset : temp.toShort());
+ temp = project->first("CharacterSet");
+ conf.CharacterSet = charSet(temp.isEmpty() ? (short)charSetNotSet : temp.toShort());
+ conf.DeleteExtensionsOnClean = project->first("DeleteExtensionsOnClean");
+ conf.ImportLibrary = conf.linker.ImportLibrary;
+ conf.IntermediateDirectory = project->first("OBJECTS_DIR");
+ conf.WholeProgramOptimization = conf.compiler.WholeProgramOptimization;
+ temp = project->first("UseOfATL");
+ if(!temp.isEmpty())
+ conf.UseOfATL = useOfATL(temp.toShort());
+ temp = project->first("UseOfMfc");
+ if(!temp.isEmpty())
+ conf.UseOfMfc = useOfMfc(temp.toShort());
+
+ // Configuration does not need parameters from
+ // these sub XML items;
+ initCustomBuildTool();
+ initPreBuildEventTools();
+ initPostBuildEventTools();
+ // Only deploy for CE projects
+ if (!project->isEmpty("CE_SDK") && !project->isEmpty("CE_ARCH"))
+ initDeploymentTool();
+ initPreLinkEventTools();
+
+ // Set definite values in both configurations
+ if (isDebug) {
+ conf.compiler.PreprocessorDefinitions.removeAll("NDEBUG");
+ } else {
+ conf.compiler.PreprocessorDefinitions += "NDEBUG";
+ }
+}
+
+void VcprojGenerator::initCompilerTool()
+{
+ QString placement = project->first("OBJECTS_DIR");
+ if(placement.isEmpty())
+ placement = ".\\";
+
+ VCConfiguration &conf = vcProject.Configuration;
+ conf.compiler.AssemblerListingLocation = placement ;
+ conf.compiler.ProgramDataBaseFileName = ".\\" ;
+ conf.compiler.ObjectFile = placement ;
+ conf.compiler.ExceptionHandling = ehNone;
+ // PCH
+ if (usePCH) {
+ conf.compiler.UsePrecompiledHeader = pchUseUsingSpecific;
+ conf.compiler.PrecompiledHeaderFile = "$(IntDir)\\" + precompPch;
+ conf.compiler.PrecompiledHeaderThrough = project->first("PRECOMPILED_HEADER");
+ conf.compiler.ForcedIncludeFiles = project->values("PRECOMPILED_HEADER");
+
+ if (conf.CompilerVersion <= NET2003) {
+ // Minimal build option triggers an Internal Compiler Error
+ // when used in conjunction with /FI and /Yu, so remove it
+ // ### work-around for a VS 2003 bug. Move to some prf file or remove completely.
+ project->values("QMAKE_CFLAGS_DEBUG").removeAll("-Gm");
+ project->values("QMAKE_CFLAGS_DEBUG").removeAll("/Gm");
+ project->values("QMAKE_CXXFLAGS_DEBUG").removeAll("-Gm");
+ project->values("QMAKE_CXXFLAGS_DEBUG").removeAll("/Gm");
+ }
+ }
+
+ conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS"));
+
+ if (project->isActiveConfig("windows"))
+ conf.compiler.PreprocessorDefinitions += "_WINDOWS";
+ else if (project->isActiveConfig("console"))
+ conf.compiler.PreprocessorDefinitions += "_CONSOLE";
+
+ conf.compiler.PreprocessorDefinitions += project->values("DEFINES");
+ conf.compiler.PreprocessorDefinitions += project->values("PRL_EXPORT_DEFINES");
+ conf.compiler.parseOptions(project->values("MSVCPROJ_INCPATH"));
+}
+
+void VcprojGenerator::initLibrarianTool()
+{
+ VCConfiguration &conf = vcProject.Configuration;
+ conf.librarian.OutputFile = "$(OutDir)\\";
+ conf.librarian.OutputFile += project->first("MSVCPROJ_TARGET");
+ conf.librarian.AdditionalOptions += project->values("QMAKE_LIBFLAGS");
+}
+
+void VcprojGenerator::initLinkerTool()
+{
+ findLibraries(); // Need to add the highest version of the libs
+ VCConfiguration &conf = vcProject.Configuration;
+ conf.linker.parseOptions(project->values("QMAKE_LFLAGS"));
+
+ foreach (const QString &libDir, project->values("QMAKE_LIBDIR")) {
+ if (libDir.startsWith("/LIBPATH:"))
+ conf.linker.AdditionalLibraryDirectories += libDir.mid(9);
+ else
+ conf.linker.AdditionalLibraryDirectories += libDir;
+ }
+
+ if (!project->values("DEF_FILE").isEmpty())
+ conf.linker.ModuleDefinitionFile = project->first("DEF_FILE");
+
+ foreach(QString libs, project->values("MSVCPROJ_LIBS")) {
+ if (libs.left(9).toUpper() == "/LIBPATH:") {
+ QStringList l = QStringList(libs);
+ conf.linker.parseOptions(l);
+ } else {
+ conf.linker.AdditionalDependencies += libs;
+ }
+ }
+
+ conf.linker.OutputFile = "$(OutDir)\\";
+ conf.linker.OutputFile += project->first("MSVCPROJ_TARGET");
+
+ if(project->isActiveConfig("dll")){
+ conf.linker.parseOptions(project->values("QMAKE_LFLAGS_QT_DLL"));
+ }
+}
+
+void VcprojGenerator::initResourceTool()
+{
+ VCConfiguration &conf = vcProject.Configuration;
+ conf.resource.PreprocessorDefinitions = conf.compiler.PreprocessorDefinitions;
+
+ // We need to add _DEBUG for the debug version of the project, since the normal compiler defines
+ // do not contain it. (The compiler defines this symbol automatically, which is wy we don't need
+ // to add it for the compiler) However, the resource tool does not do this.
+ if(project->isActiveConfig("debug"))
+ conf.resource.PreprocessorDefinitions += "_DEBUG";
+ if(project->isActiveConfig("staticlib"))
+ conf.resource.ResourceOutputFileName = "$(OutDir)\\$(InputName).res";
+}
+
+void VcprojGenerator::initIDLTool()
+{
+}
+
+void VcprojGenerator::initCustomBuildTool()
+{
+}
+
+void VcprojGenerator::initPreBuildEventTools()
+{
+}
+
+void VcprojGenerator::initPostBuildEventTools()
+{
+ VCConfiguration &conf = vcProject.Configuration;
+ if (!project->values("QMAKE_POST_LINK").isEmpty()) {
+ QStringList cmdline = VCToolBase::fixCommandLine(var("QMAKE_POST_LINK"));
+ conf.postBuild.CommandLine = cmdline;
+ conf.postBuild.Description = cmdline.join(QLatin1String("\r\n"));
+ conf.postBuild.ExcludedFromBuild = _False;
+ }
+
+ QString signature = !project->isEmpty("SIGNATURE_FILE") ? var("SIGNATURE_FILE") : var("DEFAULT_SIGNATURE");
+ bool useSignature = !signature.isEmpty() && !project->isActiveConfig("staticlib") &&
+ !project->isEmpty("CE_SDK") && !project->isEmpty("CE_ARCH");
+ if (useSignature) {
+ conf.postBuild.CommandLine.prepend(
+ QLatin1String("signtool sign /F ") + signature + QLatin1String(" \"$(TargetPath)\""));
+ conf.postBuild.ExcludedFromBuild = _False;
+ }
+
+ if (!project->values("MSVCPROJ_COPY_DLL").isEmpty()) {
+ conf.postBuild.Description += var("MSVCPROJ_COPY_DLL_DESC");
+ conf.postBuild.CommandLine += var("MSVCPROJ_COPY_DLL");
+ conf.postBuild.ExcludedFromBuild = _False;
+ }
+}
+
+void VcprojGenerator::initDeploymentTool()
+{
+ VCConfiguration &conf = vcProject.Configuration;
+ QString targetPath = project->values("deploy.path").join(" ");
+ if (targetPath.isEmpty())
+ targetPath = QString("%CSIDL_PROGRAM_FILES%\\") + project->first("TARGET");
+ if (targetPath.endsWith("/") || targetPath.endsWith("\\"))
+ targetPath.chop(1);
+
+ // Only deploy Qt libs for shared build
+ if (!project->values("QMAKE_QT_DLL").isEmpty()) {
+ QStringList& arg = project->values("MSVCPROJ_LIBS");
+ for (QStringList::ConstIterator it = arg.constBegin(); it != arg.constEnd(); ++it) {
+ if (it->contains(project->first("QMAKE_LIBDIR"))) {
+ QString dllName = *it;
+
+ if (dllName.contains(QLatin1String("QAxContainer"))
+ || dllName.contains(QLatin1String("qtmain"))
+ || dllName.contains(QLatin1String("QtUiTools")))
+ continue;
+ dllName.replace(QLatin1String(".lib") , QLatin1String(".dll"));
+ QFileInfo info(dllName);
+ conf.deployment.AdditionalFiles += info.fileName()
+ + "|" + QDir::toNativeSeparators(info.absolutePath())
+ + "|" + targetPath
+ + "|0;";
+ }
+ }
+ }
+
+ // C-runtime deployment
+ QString runtime = project->values("QT_CE_C_RUNTIME").join(QLatin1String(" "));
+ if (!runtime.isEmpty() && (runtime != QLatin1String("no"))) {
+ QString runtimeVersion = QLatin1String("msvcr");
+ QString mkspec = project->first("QMAKESPEC");
+ // If no .qmake.cache has been found, we fallback to the original mkspec
+ if (mkspec.isEmpty())
+ mkspec = project->first("QMAKESPEC_ORIGINAL");
+
+ if (!mkspec.isEmpty()) {
+ if (mkspec.endsWith("2008"))
+ runtimeVersion.append("90");
+ else
+ runtimeVersion.append("80");
+ if (project->isActiveConfig("debug"))
+ runtimeVersion.append("d");
+ runtimeVersion.append(".dll");
+
+ if (runtime == "yes") {
+ // Auto-find C-runtime
+ QString vcInstallDir = qgetenv("VCINSTALLDIR");
+ if (!vcInstallDir.isEmpty()) {
+ vcInstallDir += "\\ce\\dll\\";
+ vcInstallDir += project->values("CE_ARCH").join(QLatin1String(" "));
+ if (!QFileInfo(vcInstallDir + QDir::separator() + runtimeVersion).exists())
+ runtime.clear();
+ else
+ runtime = vcInstallDir;
+ }
+ }
+ }
+
+ if (!runtime.isEmpty() && runtime != QLatin1String("yes")) {
+ conf.deployment.AdditionalFiles += runtimeVersion
+ + "|" + QDir::toNativeSeparators(runtime)
+ + "|" + targetPath
+ + "|0;";
+ }
+ }
+
+ // foreach item in DEPLOYMENT
+ foreach(QString item, project->values("DEPLOYMENT")) {
+ // get item.path
+ QString devicePath = project->first(item + ".path");
+ if (devicePath.isEmpty())
+ devicePath = targetPath;
+ // check if item.path is relative (! either /,\ or %)
+ if (!(devicePath.at(0) == QLatin1Char('/')
+ || devicePath.at(0) == QLatin1Char('\\')
+ || devicePath.at(0) == QLatin1Char('%'))) {
+ // create output path
+ devicePath = Option::fixPathToLocalOS(QDir::cleanPath(targetPath + QLatin1Char('\\') + devicePath));
+ }
+ // foreach d in item.sources
+ // ### Qt 5: remove .sources, inconsistent with INSTALLS
+ foreach(QString source, project->values(item + ".sources") + project->values(item + ".files")) {
+ QString itemDevicePath = devicePath;
+ source = Option::fixPathToLocalOS(source);
+ QString nameFilter;
+ QFileInfo info(source);
+ QString searchPath;
+ if (info.isDir()) {
+ nameFilter = QLatin1String("*");
+ itemDevicePath += "\\" + info.fileName();
+ searchPath = info.absoluteFilePath();
+ } else {
+ nameFilter = source.split('\\').last();
+ searchPath = info.absolutePath();
+ }
+
+ int pathSize = searchPath.size();
+ QDirIterator iterator(searchPath, QStringList() << nameFilter
+ , QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks
+ , QDirIterator::Subdirectories);
+ // foreach dirIterator-entry in d
+ while(iterator.hasNext()) {
+ iterator.next();
+ QString absoluteItemPath = Option::fixPathToLocalOS(QFileInfo(iterator.filePath()).absolutePath());
+ // Identify if it is just another subdir
+ int diffSize = absoluteItemPath.size() - pathSize;
+ // write out rules
+ conf.deployment.AdditionalFiles += iterator.fileName()
+ + "|" + absoluteItemPath
+ + "|" + itemDevicePath + (diffSize ? (absoluteItemPath.right(diffSize)) : QLatin1String(""))
+ + "|0;";
+ }
+ }
+ }
+}
+
+void VcprojGenerator::initPreLinkEventTools()
+{
+ VCConfiguration &conf = vcProject.Configuration;
+ if(!project->values("QMAKE_PRE_LINK").isEmpty()) {
+ QStringList cmdline = VCToolBase::fixCommandLine(var("QMAKE_PRE_LINK"));
+ conf.preLink.CommandLine = cmdline;
+ conf.preLink.Description = cmdline.join(QLatin1String("\r\n"));
+ conf.preLink.ExcludedFromBuild = _False;
+ }
+}
+
+void VcprojGenerator::initRootFiles()
+{
+ // Note: Root files do _not_ have any filter name, filter nor GUID!
+ vcProject.RootFiles.addFiles(project->values("RC_FILE"));
+
+ vcProject.RootFiles.Project = this;
+ vcProject.RootFiles.Config = &(vcProject.Configuration);
+ vcProject.RootFiles.CustomBuild = none;
+}
+
+void VcprojGenerator::initSourceFiles()
+{
+ vcProject.SourceFiles.Name = "Source Files";
+ vcProject.SourceFiles.Filter = "cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx";
+ vcProject.SourceFiles.Guid = _GUIDSourceFiles;
+
+ vcProject.SourceFiles.addFiles(project->values("SOURCES"));
+
+ vcProject.SourceFiles.Project = this;
+ vcProject.SourceFiles.Config = &(vcProject.Configuration);
+ vcProject.SourceFiles.CustomBuild = none;
+}
+
+void VcprojGenerator::initHeaderFiles()
+{
+ vcProject.HeaderFiles.Name = "Header Files";
+ vcProject.HeaderFiles.Filter = "h;hpp;hxx;hm;inl;inc;xsd";
+ vcProject.HeaderFiles.Guid = _GUIDHeaderFiles;
+
+ vcProject.HeaderFiles.addFiles(project->values("HEADERS"));
+ if (usePCH) // Generated PCH cpp file
+ vcProject.HeaderFiles.addFile(precompH);
+
+ vcProject.HeaderFiles.Project = this;
+ vcProject.HeaderFiles.Config = &(vcProject.Configuration);
+// vcProject.HeaderFiles.CustomBuild = mocHdr;
+// addMocArguments(vcProject.HeaderFiles);
+}
+
+void VcprojGenerator::initGeneratedFiles()
+{
+ vcProject.GeneratedFiles.Name = "Generated Files";
+ vcProject.GeneratedFiles.Filter = "cpp;c;cxx;moc;h;def;odl;idl;res;";
+ vcProject.GeneratedFiles.Guid = _GUIDGeneratedFiles;
+
+ // ### These cannot have CustomBuild (mocSrc)!!
+ vcProject.GeneratedFiles.addFiles(project->values("GENERATED_SOURCES"));
+ vcProject.GeneratedFiles.addFiles(project->values("GENERATED_FILES"));
+ vcProject.GeneratedFiles.addFiles(project->values("IDLSOURCES"));
+ vcProject.GeneratedFiles.addFiles(project->values("RES_FILE"));
+ vcProject.GeneratedFiles.addFiles(project->values("QMAKE_IMAGE_COLLECTION")); // compat
+ if(!extraCompilerOutputs.isEmpty())
+ vcProject.GeneratedFiles.addFiles(extraCompilerOutputs.keys());
+
+ vcProject.GeneratedFiles.Project = this;
+ vcProject.GeneratedFiles.Config = &(vcProject.Configuration);
+// vcProject.GeneratedFiles.CustomBuild = mocSrc;
+}
+
+void VcprojGenerator::initLexYaccFiles()
+{
+ vcProject.LexYaccFiles.Name = "Lex / Yacc Files";
+ vcProject.LexYaccFiles.ParseFiles = _False;
+ vcProject.LexYaccFiles.Filter = "l;y";
+ vcProject.LexYaccFiles.Guid = _GUIDLexYaccFiles;
+
+ vcProject.LexYaccFiles.addFiles(project->values("LEXSOURCES"));
+ vcProject.LexYaccFiles.addFiles(project->values("YACCSOURCES"));
+
+ vcProject.LexYaccFiles.Project = this;
+ vcProject.LexYaccFiles.Config = &(vcProject.Configuration);
+ vcProject.LexYaccFiles.CustomBuild = lexyacc;
+}
+
+void VcprojGenerator::initTranslationFiles()
+{
+ vcProject.TranslationFiles.Name = "Translation Files";
+ vcProject.TranslationFiles.ParseFiles = _False;
+ vcProject.TranslationFiles.Filter = "ts;xlf";
+ vcProject.TranslationFiles.Guid = _GUIDTranslationFiles;
+
+ vcProject.TranslationFiles.addFiles(project->values("TRANSLATIONS"));
+
+ vcProject.TranslationFiles.Project = this;
+ vcProject.TranslationFiles.Config = &(vcProject.Configuration);
+ vcProject.TranslationFiles.CustomBuild = none;
+}
+
+void VcprojGenerator::initFormFiles()
+{
+ vcProject.FormFiles.Name = "Form Files";
+ vcProject.FormFiles.ParseFiles = _False;
+ vcProject.FormFiles.Filter = "ui";
+ vcProject.FormFiles.Guid = _GUIDFormFiles;
+
+ vcProject.FormFiles.addFiles(project->values("FORMS"));
+ vcProject.FormFiles.addFiles(project->values("FORMS3"));
+
+ vcProject.FormFiles.Project = this;
+ vcProject.FormFiles.Config = &(vcProject.Configuration);
+ vcProject.FormFiles.CustomBuild = none;
+}
+
+void VcprojGenerator::initResourceFiles()
+{
+ vcProject.ResourceFiles.Name = "Resource Files";
+ vcProject.ResourceFiles.ParseFiles = _False;
+ vcProject.ResourceFiles.Filter = "qrc;*"; //"rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;ts;xlf;qrc";
+ vcProject.ResourceFiles.Guid = _GUIDResourceFiles;
+
+ // Bad hack, please look away -------------------------------------
+ QString rcc_dep_cmd = project->values("rcc.depend_command").join(" ");
+ if(!rcc_dep_cmd.isEmpty()) {
+ QStringList qrc_files = project->values("RESOURCES");
+ QStringList deps;
+ if(!qrc_files.isEmpty()) {
+ for (int i = 0; i < qrc_files.count(); ++i) {
+ char buff[256];
+ QString dep_cmd = replaceExtraCompilerVariables(rcc_dep_cmd, qrc_files.at(i),"");
+
+ dep_cmd = Option::fixPathToLocalOS(dep_cmd, true, false);
+ if(canExecute(dep_cmd)) {
+ dep_cmd.prepend(QLatin1String("cd ")
+ + escapeFilePath(Option::fixPathToLocalOS(Option::output_dir, false))
+ + QLatin1String(" && "));
+ if(FILE *proc = QT_POPEN(dep_cmd.toLatin1().constData(), "r")) {
+ QString indeps;
+ while(!feof(proc)) {
+ int read_in = (int)fread(buff, 1, 255, proc);
+ if(!read_in)
+ break;
+ indeps += QByteArray(buff, read_in);
+ }
+ QT_PCLOSE(proc);
+ if(!indeps.isEmpty())
+ deps += fileFixify(indeps.replace('\n', ' ').simplified().split(' '),
+ QString(), Option::output_dir);
+ }
+ }
+ }
+ vcProject.ResourceFiles.addFiles(deps);
+ }
+ }
+ // You may look again --------------------------------------------
+
+ vcProject.ResourceFiles.addFiles(project->values("RESOURCES"));
+ vcProject.ResourceFiles.addFiles(project->values("IMAGES"));
+
+ vcProject.ResourceFiles.Project = this;
+ vcProject.ResourceFiles.Config = &(vcProject.Configuration);
+ vcProject.ResourceFiles.CustomBuild = none;
+}
+
+void VcprojGenerator::initExtraCompilerOutputs()
+{
+ QStringList otherFilters;
+ otherFilters << "FORMS"
+ << "FORMS3"
+ << "GENERATED_FILES"
+ << "GENERATED_SOURCES"
+ << "HEADERS"
+ << "IDLSOURCES"
+ << "IMAGES"
+ << "LEXSOURCES"
+ << "QMAKE_IMAGE_COLLECTION"
+ << "RC_FILE"
+ << "RESOURCES"
+ << "RES_FILE"
+ << "SOURCES"
+ << "TRANSLATIONS"
+ << "YACCSOURCES";
+ const QStringList &quc = project->values("QMAKE_EXTRA_COMPILERS");
+ for(QStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) {
+ QString extracompilerName = project->first((*it) + ".name");
+ if (extracompilerName.isEmpty())
+ extracompilerName = (*it);
+
+ // Create an extra compiler filter and add the files
+ VCFilter extraCompile;
+ extraCompile.Name = extracompilerName;
+ extraCompile.ParseFiles = _False;
+ extraCompile.Filter = "";
+ extraCompile.Guid = QString(_GUIDExtraCompilerFiles) + "-" + (*it);
+
+
+ // If the extra compiler has a variable_out set the output file
+ // is added to an other file list, and does not need its own..
+ bool addOnInput = hasBuiltinCompiler(project->first((*it) + ".output"));
+ QString tmp_other_out = project->first((*it) + ".variable_out");
+ if (!tmp_other_out.isEmpty() && !addOnInput)
+ continue;
+
+ if (!addOnInput) {
+ QString tmp_out = project->first((*it) + ".output");
+ if (project->values((*it) + ".CONFIG").indexOf("combine") != -1) {
+ // Combined output, only one file result
+ extraCompile.addFile(
+ Option::fixPathToTargetOS(replaceExtraCompilerVariables(tmp_out, QString(), QString()), false));
+ } else {
+ // One output file per input
+ QStringList tmp_in = project->values(project->first((*it) + ".input"));
+ for (int i = 0; i < tmp_in.count(); ++i) {
+ const QString &filename = tmp_in.at(i);
+ if (extraCompilerSources.contains(filename))
+ extraCompile.addFile(
+ Option::fixPathToTargetOS(replaceExtraCompilerVariables(filename, tmp_out, QString()), false));
+ }
+ }
+ } else {
+ // In this case we the outputs have a built-in compiler, so we cannot add the custom
+ // build steps there. So, we turn it around and add it to the input files instead,
+ // provided that the input file variable is not handled already (those in otherFilters
+ // are handled, so we avoid them).
+ QStringList inputVars = project->values((*it) + ".input");
+ foreach(QString inputVar, inputVars) {
+ if (!otherFilters.contains(inputVar)) {
+ QStringList tmp_in = project->values(inputVar);
+ for (int i = 0; i < tmp_in.count(); ++i) {
+ const QString &filename = tmp_in.at(i);
+ if (extraCompilerSources.contains(filename))
+ extraCompile.addFile(
+ Option::fixPathToTargetOS(replaceExtraCompilerVariables(filename, QString(), QString()), false));
+ }
+ }
+ }
+ }
+ extraCompile.Project = this;
+ extraCompile.Config = &(vcProject.Configuration);
+ extraCompile.CustomBuild = none;
+
+ vcProject.ExtraCompilersFiles.append(extraCompile);
+ }
+}
+
+void VcprojGenerator::initOld()
+{
+ // $$QMAKE.. -> $$MSVCPROJ.. -------------------------------------
+ project->values("MSVCPROJ_LIBS") += project->values("QMAKE_LIBS");
+ project->values("MSVCPROJ_LIBS") += project->values("QMAKE_LIBS_PRIVATE");
+ QStringList &incs = project->values("INCLUDEPATH");
+ for(QStringList::Iterator incit = incs.begin(); incit != incs.end(); ++incit) {
+ QString inc = (*incit);
+ if (!inc.startsWith('"') && !inc.endsWith('"'))
+ inc = QString("\"%1\"").arg(inc); // Quote all paths if not quoted already
+ project->values("MSVCPROJ_INCPATH").append("-I" + inc);
+ }
+ project->values("MSVCPROJ_INCPATH").append("-I" + specdir());
+
+ QString dest;
+ project->values("MSVCPROJ_TARGET") = QStringList(project->first("TARGET"));
+ Option::fixPathToTargetOS(project->first("TARGET"));
+ dest = project->first("TARGET") + project->first("TARGET_EXT");
+ project->values("MSVCPROJ_TARGET") = QStringList(dest);
+
+ // DLL COPY ------------------------------------------------------
+ if(project->isActiveConfig("dll") && !project->values("DLLDESTDIR").isEmpty()) {
+ QStringList dlldirs = project->values("DLLDESTDIR");
+ QString copydll("");
+ QStringList::Iterator dlldir;
+ for(dlldir = dlldirs.begin(); dlldir != dlldirs.end(); ++dlldir) {
+ if(!copydll.isEmpty())
+ copydll += " && ";
+ copydll += "copy \"$(TargetPath)\" \"" + *dlldir + "\"";
+ }
+
+ QString deststr("Copy " + dest + " to ");
+ for(dlldir = dlldirs.begin(); dlldir != dlldirs.end();) {
+ deststr += *dlldir;
+ ++dlldir;
+ if(dlldir != dlldirs.end())
+ deststr += ", ";
+ }
+
+ project->values("MSVCPROJ_COPY_DLL").append(copydll);
+ project->values("MSVCPROJ_COPY_DLL_DESC").append(deststr);
+ }
+
+ project->values("QMAKE_INTERNAL_PRL_LIBS") << "MSVCPROJ_LIBS";
+
+ // Verbose output if "-d -d"...
+ outputVariables();
+}
+
+// ------------------------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------------------------
+
+VCProjectWriter *VcprojGenerator::createProjectWriter()
+{
+ return new VCProjectWriter;
+}
+
+QString VcprojGenerator::replaceExtraCompilerVariables(const QString &var, const QStringList &in, const QStringList &out)
+{
+ QString ret = MakefileGenerator::replaceExtraCompilerVariables(var, in, out);
+
+ QStringList &defines = project->values("VCPROJ_MAKEFILE_DEFINES");
+ if(defines.isEmpty())
+ defines.append(varGlue("PRL_EXPORT_DEFINES"," -D"," -D","") +
+ varGlue("DEFINES"," -D"," -D",""));
+ ret.replace("$(DEFINES)", defines.first());
+
+ QStringList &incpath = project->values("VCPROJ_MAKEFILE_INCPATH");
+ if(incpath.isEmpty() && !this->var("MSVCPROJ_INCPATH").isEmpty())
+ incpath.append(this->var("MSVCPROJ_INCPATH"));
+ ret.replace("$(INCPATH)", incpath.join(" "));
+
+ return ret;
+}
+
+bool VcprojGenerator::openOutput(QFile &file, const QString &/*build*/) const
+{
+ QString outdir;
+ if(!file.fileName().isEmpty()) {
+ QFileInfo fi(fileInfo(file.fileName()));
+ if(fi.isDir())
+ outdir = file.fileName() + QDir::separator();
+ }
+ if(!outdir.isEmpty() || file.fileName().isEmpty()) {
+ QString ext = project->first("VCPROJ_EXTENSION");
+ if(project->first("TEMPLATE") == "vcsubdirs")
+ ext = project->first("VCSOLUTION_EXTENSION");
+ QString outputName = unescapeFilePath(project->first("TARGET"));
+ if (!project->first("MAKEFILE").isEmpty())
+ outputName = project->first("MAKEFILE");
+ file.setFileName(outdir + outputName + ext);
+ }
+ return Win32MakefileGenerator::openOutput(file, QString());
+}
+
+QString VcprojGenerator::fixFilename(QString ofile) const
+{
+ ofile = Option::fixPathToLocalOS(ofile);
+ int slashfind = ofile.lastIndexOf(Option::dir_sep);
+ if(slashfind == -1) {
+ ofile = ofile.replace('-', '_');
+ } else {
+ int hyphenfind = ofile.indexOf('-', slashfind);
+ while (hyphenfind != -1 && slashfind < hyphenfind) {
+ ofile = ofile.replace(hyphenfind, 1, '_');
+ hyphenfind = ofile.indexOf('-', hyphenfind + 1);
+ }
+ }
+ return ofile;
+}
+
+QString VcprojGenerator::findTemplate(QString file)
+{
+ QString ret;
+ if(!exists((ret = file)) &&
+ !exists((ret = QString(Option::mkfile::qmakespec + "/" + file))) &&
+ !exists((ret = QString(QLibraryInfo::location(QLibraryInfo::DataPath) + "/win32-msvc.net/" + file))) &&
+ !exists((ret = QString(QLibraryInfo::location(QLibraryInfo::DataPath) + "/win32-msvc2002/" + file))) &&
+ !exists((ret = QString(QLibraryInfo::location(QLibraryInfo::DataPath) + "/win32-msvc2003/" + file))) &&
+ !exists((ret = QString(QLibraryInfo::location(QLibraryInfo::DataPath) + "/win32-msvc2005/" + file))) &&
+ !exists((ret = QString(QLibraryInfo::location(QLibraryInfo::DataPath) + "/win32-msvc2008/" + file))))
+ return "";
+ debug_msg(1, "Generator: MSVC.NET: Found template \'%s\'", ret.toLatin1().constData());
+ return ret;
+}
+
+void VcprojGenerator::outputVariables()
+{
+#if 0
+ qDebug("Generator: MSVC.NET: List of current variables:");
+ for(QMap<QString, QStringList>::ConstIterator it = project->variables().begin(); it != project->variables().end(); ++it)
+ qDebug("Generator: MSVC.NET: %s => %s", qPrintable(it.key()), qPrintable(it.value().join(" | ")));
+#endif
+}
+
+QT_END_NAMESPACE
diff --git a/qmake/generators/win32/msvc_vcproj.h b/qmake/generators/win32/msvc_vcproj.h
new file mode 100644
index 0000000000..afe8f9ff21
--- /dev/null
+++ b/qmake/generators/win32/msvc_vcproj.h
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the qmake application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MSVC_VCPROJ_H
+#define MSVC_VCPROJ_H
+
+#include "winmakefile.h"
+#include "msvc_objectmodel.h"
+
+QT_BEGIN_NAMESPACE
+
+enum Target {
+ Application,
+ SharedLib,
+ StaticLib
+};
+
+struct QUuid;
+class VcprojGenerator : public Win32MakefileGenerator
+{
+ bool init_flag;
+ bool writeVcprojParts(QTextStream &);
+
+ bool writeMakefile(QTextStream &);
+ bool writeProjectMakefile();
+
+ QString findTemplate(QString file);
+ void init();
+
+public:
+ VcprojGenerator();
+ ~VcprojGenerator();
+
+ QString defaultMakefile() const;
+ QString precompH, precompHFilename, precompCPP,
+ precompObj, precompPch;
+ bool autogenPrecompCPP;
+ static bool hasBuiltinCompiler(const QString &file);
+
+ QMap<QString, QStringList> extraCompilerSources;
+ QMap<QString, QStringList> extraCompilerOutputs;
+ bool usePCH;
+ VCProjectWriter *projectWriter;
+
+protected:
+ virtual VCProjectWriter *createProjectWriter();
+ virtual bool doDepends() const { return false; } //never necesary
+ virtual void processSources() { filterIncludedFiles("SOURCES"); filterIncludedFiles("GENERATED_SOURCES"); }
+ virtual QString replaceExtraCompilerVariables(const QString &, const QStringList &, const QStringList &);
+ inline QString replaceExtraCompilerVariables(const QString &val, const QString &in, const QString &out)
+ { return MakefileGenerator::replaceExtraCompilerVariables(val, in, out); }
+ virtual bool supportsMetaBuild() { return true; }
+ virtual bool supportsMergedBuilds() { return true; }
+ virtual bool mergeBuildProject(MakefileGenerator *other);
+
+ virtual bool openOutput(QFile &file, const QString &build) const;
+ virtual bool findLibraries();
+ virtual void outputVariables();
+ QString fixFilename(QString ofile) const;
+
+ void initOld();
+ virtual void initProject();
+ void initConfiguration();
+ void initCompilerTool();
+ void initLinkerTool();
+ void initLibrarianTool();
+ void initResourceTool();
+ void initIDLTool();
+ void initCustomBuildTool();
+ void initPreBuildEventTools();
+ void initPostBuildEventTools();
+ void initDeploymentTool();
+ void initPreLinkEventTools();
+ void initRootFiles();
+ void initSourceFiles();
+ void initHeaderFiles();
+ void initGeneratedFiles();
+ void initTranslationFiles();
+ void initFormFiles();
+ void initResourceFiles();
+ void initLexYaccFiles();
+ void initExtraCompilerOutputs();
+
+ void writeSubDirs(QTextStream &t); // Called from VCXProj backend
+ QUuid getProjectUUID(const QString &filename=QString()); // Called from VCXProj backend
+
+ Target projectTarget;
+
+ // Used for single project
+ VCProjectSingleConfig vcProject;
+
+ // Holds all configurations for glue (merged) project
+ QList<VcprojGenerator*> mergedProjects;
+
+private:
+ QStringList collectSubDirs(QMakeProject *proj);
+ QUuid increaseUUID(const QUuid &id);
+ friend class VCFilter;
+};
+
+inline QString VcprojGenerator::defaultMakefile() const
+{
+ return project->first("TARGET") + project->first("VCPROJ_EXTENSION");
+}
+
+inline bool VcprojGenerator::findLibraries()
+{
+ return Win32MakefileGenerator::findLibraries("MSVCPROJ_LIBS");
+}
+
+QT_END_NAMESPACE
+
+#endif // MSVC_VCPROJ_H
diff --git a/qmake/generators/win32/msvc_vcxproj.cpp b/qmake/generators/win32/msvc_vcxproj.cpp
new file mode 100644
index 0000000000..1e7c4b7a93
--- /dev/null
+++ b/qmake/generators/win32/msvc_vcxproj.cpp
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the qmake application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "msvc_vcxproj.h"
+#include "msbuild_objectmodel.h"
+#include <qdir.h>
+#include <qdiriterator.h>
+#include <quuid.h>
+
+
+QT_BEGIN_NAMESPACE
+// Filter GUIDs (Do NOT change these!) ------------------------------
+const char _GUIDSourceFiles[] = "{4FC737F1-C7A5-4376-A066-2A32D752A2FF}";
+const char _GUIDHeaderFiles[] = "{93995380-89BD-4b04-88EB-625FBE52EBFB}";
+const char _GUIDGeneratedFiles[] = "{71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}";
+const char _GUIDResourceFiles[] = "{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}";
+const char _GUIDLexYaccFiles[] = "{E12AE0D2-192F-4d59-BD23-7D3FA58D3183}";
+const char _GUIDTranslationFiles[] = "{639EADAA-A684-42e4-A9AD-28FC9BCB8F7C}";
+const char _GUIDFormFiles[] = "{99349809-55BA-4b9d-BF79-8FDBB0286EB3}";
+const char _GUIDExtraCompilerFiles[] = "{E0D8C965-CC5F-43d7-AD63-FAEF0BBC0F85}";
+QT_END_NAMESPACE
+
+QT_BEGIN_NAMESPACE
+
+
+VcxprojGenerator::VcxprojGenerator() : VcprojGenerator()
+{
+}
+
+VCProjectWriter *VcxprojGenerator::createProjectWriter()
+{
+ return new VCXProjectWriter;
+}
+
+QT_END_NAMESPACE
+
diff --git a/qmake/generators/win32/msvc_vcxproj.h b/qmake/generators/win32/msvc_vcxproj.h
new file mode 100644
index 0000000000..3283cc7493
--- /dev/null
+++ b/qmake/generators/win32/msvc_vcxproj.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the qmake application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MSVC_VCXPROJ_H
+#define MSVC_VCXPROJ_H
+
+#include "winmakefile.h"
+#include "msbuild_objectmodel.h"
+#include "msvc_vcproj.h"
+
+QT_BEGIN_NAMESPACE
+
+class VcxprojGenerator : public VcprojGenerator
+{
+public:
+ VcxprojGenerator();
+ ~VcxprojGenerator();
+
+protected:
+ virtual VCProjectWriter *createProjectWriter();
+
+private:
+ friend class VCFilter;
+
+};
+
+inline VcxprojGenerator::~VcxprojGenerator()
+{ }
+
+QT_END_NAMESPACE
+
+#endif // MSVC_VCXPROJ_H
diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp
new file mode 100644
index 0000000000..ef234ec506
--- /dev/null
+++ b/qmake/generators/win32/winmakefile.cpp
@@ -0,0 +1,895 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the qmake application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "winmakefile.h"
+#include "option.h"
+#include "project.h"
+#include "meta.h"
+#include <qtextstream.h>
+#include <qstring.h>
+#include <qhash.h>
+#include <qregexp.h>
+#include <qstringlist.h>
+#include <qdir.h>
+#include <stdlib.h>
+
+QT_BEGIN_NAMESPACE
+
+Win32MakefileGenerator::Win32MakefileGenerator() : MakefileGenerator()
+{
+}
+
+int
+Win32MakefileGenerator::findHighestVersion(const QString &d, const QString &stem, const QString &ext)
+{
+ QString bd = Option::fixPathToLocalOS(d, true);
+ if(!exists(bd))
+ return -1;
+
+ QString dllStem = stem + QTDLL_POSTFIX;
+ QMakeMetaInfo libinfo;
+ bool libInfoRead = libinfo.readLib(bd + Option::dir_sep + dllStem);
+
+ // If the library, for which we're trying to find the highest version
+ // number, is a static library
+ if (libInfoRead && libinfo.values("QMAKE_PRL_CONFIG").contains("staticlib"))
+ return -1;
+
+ if(!project->values("QMAKE_" + stem.toUpper() + "_VERSION_OVERRIDE").isEmpty())
+ return project->values("QMAKE_" + stem.toUpper() + "_VERSION_OVERRIDE").first().toInt();
+
+ int biggest=-1;
+ if(!project->isActiveConfig("no_versionlink")) {
+ static QHash<QString, QStringList> dirEntryListCache;
+ QStringList entries = dirEntryListCache.value(bd);
+ if (entries.isEmpty()) {
+ QDir dir(bd);
+ entries = dir.entryList();
+ dirEntryListCache.insert(bd, entries);
+ }
+
+ QRegExp regx(QString("((lib)?%1([0-9]*)).(%2|prl)$").arg(dllStem).arg(ext), Qt::CaseInsensitive);
+ for(QStringList::Iterator it = entries.begin(); it != entries.end(); ++it) {
+ if(regx.exactMatch((*it))) {
+ if (!regx.cap(3).isEmpty()) {
+ bool ok = true;
+ int num = regx.cap(3).toInt(&ok);
+ biggest = qMax(biggest, (!ok ? -1 : num));
+ }
+ }
+ }
+ }
+ if(libInfoRead
+ && !libinfo.values("QMAKE_PRL_CONFIG").contains("staticlib")
+ && !libinfo.isEmpty("QMAKE_PRL_VERSION"))
+ biggest = qMax(biggest, libinfo.first("QMAKE_PRL_VERSION").replace(".", "").toInt());
+ return biggest;
+}
+
+bool
+Win32MakefileGenerator::findLibraries(const QString &where)
+{
+ QStringList &l = project->values(where);
+ QList<QMakeLocalFileName> dirs;
+ {
+ QStringList &libpaths = project->values("QMAKE_LIBDIR");
+ for(QStringList::Iterator libpathit = libpaths.begin();
+ libpathit != libpaths.end(); ++libpathit)
+ dirs.append(QMakeLocalFileName((*libpathit)));
+ }
+ for(QStringList::Iterator it = l.begin(); it != l.end();) {
+ QChar quote;
+ bool modified_opt = false, remove = false;
+ QString opt = (*it).trimmed();
+ if((opt[0] == '\'' || opt[0] == '"') && opt[(int)opt.length()-1] == opt[0]) {
+ quote = opt[0];
+ opt = opt.mid(1, opt.length()-2);
+ }
+ if(opt.startsWith("/LIBPATH:")) {
+ dirs.append(QMakeLocalFileName(opt.mid(9)));
+ } else if(opt.startsWith("-L") || opt.startsWith("/L")) {
+ QString libpath = opt.mid(2);
+ QMakeLocalFileName l(libpath);
+ if(!dirs.contains(l)) {
+ dirs.append(l);
+ modified_opt = true;
+ if (!quote.isNull()) {
+ libpath = quote + libpath + quote;
+ quote = QChar();
+ }
+ (*it) = "/LIBPATH:" + libpath;
+ } else {
+ remove = true;
+ }
+ } else if(opt.startsWith("-l") || opt.startsWith("/l")) {
+ QString lib = opt.right(opt.length() - 2), out;
+ if(!lib.isEmpty()) {
+ QString suffix;
+ if(!project->isEmpty("QMAKE_" + lib.toUpper() + "_SUFFIX"))
+ suffix = project->first("QMAKE_" + lib.toUpper() + "_SUFFIX");
+ for(QList<QMakeLocalFileName>::Iterator it = dirs.begin();
+ it != dirs.end(); ++it) {
+ QString extension;
+ int ver = findHighestVersion((*it).local(), lib);
+ if(ver > 0)
+ extension += QString::number(ver);
+ extension += suffix;
+ extension += ".lib";
+ if(QMakeMetaInfo::libExists((*it).local() + Option::dir_sep + lib) ||
+ exists((*it).local() + Option::dir_sep + lib + extension)) {
+ out = (*it).real() + Option::dir_sep + lib + extension;
+ if (out.contains(QLatin1Char(' '))) {
+ out.prepend(QLatin1Char('\"'));
+ out.append(QLatin1Char('\"'));
+ }
+ break;
+ }
+ }
+ }
+ if(out.isEmpty())
+ out = lib + ".lib";
+ modified_opt = true;
+ (*it) = out;
+ } else if(!exists(Option::fixPathToLocalOS(opt))) {
+ QList<QMakeLocalFileName> lib_dirs;
+ QString file = opt;
+ int slsh = file.lastIndexOf(Option::dir_sep);
+ if(slsh != -1) {
+ lib_dirs.append(QMakeLocalFileName(file.left(slsh+1)));
+ file = file.right(file.length() - slsh - 1);
+ } else {
+ lib_dirs = dirs;
+ }
+ if(file.endsWith(".lib")) {
+ file = file.left(file.length() - 4);
+ if(!file.at(file.length()-1).isNumber()) {
+ QString suffix;
+ if(!project->isEmpty("QMAKE_" + file.section(Option::dir_sep, -1).toUpper() + "_SUFFIX"))
+ suffix = project->first("QMAKE_" + file.section(Option::dir_sep, -1).toUpper() + "_SUFFIX");
+ for(QList<QMakeLocalFileName>::Iterator dep_it = lib_dirs.begin(); dep_it != lib_dirs.end(); ++dep_it) {
+ QString lib_tmpl(file + "%1" + suffix + ".lib");
+ int ver = findHighestVersion((*dep_it).local(), file);
+ if(ver != -1) {
+ if(ver)
+ lib_tmpl = lib_tmpl.arg(ver);
+ else
+ lib_tmpl = lib_tmpl.arg("");
+ if(slsh != -1) {
+ QString dir = (*dep_it).real();
+ if(!dir.endsWith(Option::dir_sep))
+ dir += Option::dir_sep;
+ lib_tmpl.prepend(dir);
+ }
+ modified_opt = true;
+ (*it) = lib_tmpl;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if(remove) {
+ it = l.erase(it);
+ } else {
+ if(!quote.isNull() && modified_opt)
+ (*it) = quote + (*it) + quote;
+ ++it;
+ }
+ }
+ return true;
+}
+
+void
+Win32MakefileGenerator::processPrlFiles()
+{
+ QHash<QString, bool> processed;
+ QList<QMakeLocalFileName> libdirs;
+ {
+ QStringList &libpaths = project->values("QMAKE_LIBDIR");
+ for(QStringList::Iterator libpathit = libpaths.begin(); libpathit != libpaths.end(); ++libpathit)
+ libdirs.append(QMakeLocalFileName((*libpathit)));
+ }
+ for(bool ret = false; true; ret = false) {
+ //read in any prl files included..
+ QStringList l_out;
+ QString where = "QMAKE_LIBS";
+ if(!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS"))
+ where = project->first("QMAKE_INTERNAL_PRL_LIBS");
+ QStringList l = project->values(where);
+ for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
+ QString opt = (*it).trimmed();
+ if((opt[0] == '\'' || opt[0] == '"') && opt[(int)opt.length()-1] == opt[0])
+ opt = opt.mid(1, opt.length()-2);
+ if(opt.startsWith("/")) {
+ if(opt.startsWith("/LIBPATH:")) {
+ QMakeLocalFileName l(opt.mid(9));
+ if(!libdirs.contains(l))
+ libdirs.append(l);
+ }
+ } else if(!processed.contains(opt)) {
+ if(processPrlFile(opt)) {
+ processed.insert(opt, true);
+ ret = true;
+ } else if(QDir::isRelativePath(opt) || opt.startsWith("-l")) {
+ QString tmp;
+ if (opt.startsWith("-l"))
+ tmp = opt.mid(2);
+ else
+ tmp = opt;
+ for(QList<QMakeLocalFileName>::Iterator it = libdirs.begin(); it != libdirs.end(); ++it) {
+ QString prl = (*it).local() + Option::dir_sep + tmp;
+ // the original is used as the key
+ QString orgprl = prl;
+ if(processed.contains(prl)) {
+ break;
+ } else if(processPrlFile(prl)) {
+ processed.insert(orgprl, true);
+ ret = true;
+ break;
+ }
+ }
+ }
+ }
+ if(!opt.isEmpty())
+ l_out.append(opt);
+ }
+ if(ret)
+ l = l_out;
+ else
+ break;
+ }
+}
+
+
+void Win32MakefileGenerator::processVars()
+{
+ //If the TARGET looks like a path split it into DESTDIR and the resulting TARGET
+ if(!project->isEmpty("TARGET")) {
+ QString targ = project->first("TARGET");
+ int slsh = qMax(targ.lastIndexOf('/'), targ.lastIndexOf(Option::dir_sep));
+ if(slsh != -1) {
+ if(project->isEmpty("DESTDIR"))
+ project->values("DESTDIR").append("");
+ else if(project->first("DESTDIR").right(1) != Option::dir_sep)
+ project->values("DESTDIR") = QStringList(project->first("DESTDIR") + Option::dir_sep);
+ project->values("DESTDIR") = QStringList(project->first("DESTDIR") + targ.left(slsh+1));
+ project->values("TARGET") = QStringList(targ.mid(slsh+1));
+ }
+ }
+
+ project->values("QMAKE_ORIG_TARGET") = project->values("TARGET");
+ if (project->isEmpty("QMAKE_PROJECT_NAME"))
+ project->values("QMAKE_PROJECT_NAME") = project->values("QMAKE_ORIG_TARGET");
+ else if (project->first("TEMPLATE").startsWith("vc"))
+ project->values("MAKEFILE") = project->values("QMAKE_PROJECT_NAME");
+
+ if (!project->values("QMAKE_INCDIR").isEmpty())
+ project->values("INCLUDEPATH") += project->values("QMAKE_INCDIR");
+
+ if (!project->values("VERSION").isEmpty()) {
+ QStringList l = project->first("VERSION").split('.');
+ if (l.size() > 0)
+ project->values("VER_MAJ").append(l[0]);
+ if (l.size() > 1)
+ project->values("VER_MIN").append(l[1]);
+ }
+
+ // TARGET_VERSION_EXT will be used to add a version number onto the target name
+ if (project->values("TARGET_VERSION_EXT").isEmpty()
+ && !project->values("VER_MAJ").isEmpty()
+ && project->values("QMAKE_SYMBIAN_SHLIB").isEmpty())
+ project->values("TARGET_VERSION_EXT").append(project->values("VER_MAJ").first());
+
+ if(project->isEmpty("QMAKE_COPY_FILE"))
+ project->values("QMAKE_COPY_FILE").append("$(COPY)");
+ if(project->isEmpty("QMAKE_COPY_DIR"))
+ project->values("QMAKE_COPY_DIR").append("xcopy /s /q /y /i");
+ if(project->isEmpty("QMAKE_INSTALL_FILE"))
+ project->values("QMAKE_INSTALL_FILE").append("$(COPY_FILE)");
+ if(project->isEmpty("QMAKE_INSTALL_PROGRAM"))
+ project->values("QMAKE_INSTALL_PROGRAM").append("$(COPY_FILE)");
+ if(project->isEmpty("QMAKE_INSTALL_DIR"))
+ project->values("QMAKE_INSTALL_DIR").append("$(COPY_DIR)");
+
+ fixTargetExt();
+ processRcFileVar();
+ processFileTagsVar();
+
+ QStringList &incDir = project->values("INCLUDEPATH");
+ for(QStringList::Iterator incDir_it = incDir.begin(); incDir_it != incDir.end(); ++incDir_it) {
+ if(!(*incDir_it).isEmpty())
+ (*incDir_it) = Option::fixPathToTargetOS((*incDir_it), false, false);
+ }
+ QStringList &libDir = project->values("QMAKE_LIBDIR");
+ for(QStringList::Iterator libDir_it = libDir.begin(); libDir_it != libDir.end(); ++libDir_it) {
+ if(!(*libDir_it).isEmpty())
+ (*libDir_it) = Option::fixPathToTargetOS((*libDir_it), false, false);
+ }
+
+ if (project->values("TEMPLATE").contains("app")) {
+ project->values("QMAKE_CFLAGS") += project->values("QMAKE_CFLAGS_APP");
+ project->values("QMAKE_CXXFLAGS") += project->values("QMAKE_CXXFLAGS_APP");
+ project->values("QMAKE_LFLAGS") += project->values("QMAKE_LFLAGS_APP");
+ } else if (project->values("TEMPLATE").contains("lib") && project->isActiveConfig("dll")) {
+ if(!project->isActiveConfig("plugin") || !project->isActiveConfig("plugin_no_share_shlib_cflags")) {
+ project->values("QMAKE_CFLAGS") += project->values("QMAKE_CFLAGS_SHLIB");
+ project->values("QMAKE_CXXFLAGS") += project->values("QMAKE_CXXFLAGS_SHLIB");
+ }
+ if (project->isActiveConfig("plugin")) {
+ project->values("QMAKE_CFLAGS") += project->values("QMAKE_CFLAGS_PLUGIN");
+ project->values("QMAKE_CXXFLAGS") += project->values("QMAKE_CXXFLAGS_PLUGIN");
+ project->values("QMAKE_LFLAGS") += project->values("QMAKE_LFLAGS_PLUGIN");
+ } else {
+ project->values("QMAKE_LFLAGS") += project->values("QMAKE_LFLAGS_SHLIB");
+ }
+ }
+}
+
+void Win32MakefileGenerator::fixTargetExt()
+{
+ if (project->isEmpty("QMAKE_EXTENSION_STATICLIB"))
+ project->values("QMAKE_EXTENSION_STATICLIB").append("lib");
+ if (project->isEmpty("QMAKE_EXTENSION_SHLIB"))
+ project->values("QMAKE_EXTENSION_SHLIB").append("dll");
+
+ if (!project->values("QMAKE_APP_FLAG").isEmpty()) {
+ project->values("TARGET_EXT").append(".exe");
+ } else if (project->isActiveConfig("shared")) {
+ project->values("TARGET_EXT").append(project->first("TARGET_VERSION_EXT") + "."
+ + project->first("QMAKE_EXTENSION_SHLIB"));
+ project->values("TARGET").first() = project->first("QMAKE_PREFIX_SHLIB") + project->first("TARGET");
+ } else {
+ project->values("TARGET_EXT").append("." + project->first("QMAKE_EXTENSION_STATICLIB"));
+ project->values("TARGET").first() = project->first("QMAKE_PREFIX_STATICLIB") + project->first("TARGET");
+ }
+}
+
+void Win32MakefileGenerator::processRcFileVar()
+{
+ if (Option::qmake_mode == Option::QMAKE_GENERATE_NOTHING)
+ return;
+
+ if (((!project->values("VERSION").isEmpty())
+ && project->values("RC_FILE").isEmpty()
+ && project->values("RES_FILE").isEmpty()
+ && !project->isActiveConfig("no_generated_target_info")
+ && (project->isActiveConfig("shared") || !project->values("QMAKE_APP_FLAG").isEmpty()))
+ || !project->values("QMAKE_WRITE_DEFAULT_RC").isEmpty()){
+
+ QByteArray rcString;
+ QTextStream ts(&rcString, QFile::WriteOnly);
+
+ QStringList vers = project->values("VERSION").first().split(".");
+ for (int i = vers.size(); i < 4; i++)
+ vers += "0";
+ QString versionString = vers.join(".");
+
+ QString companyName;
+ if (!project->values("QMAKE_TARGET_COMPANY").isEmpty())
+ companyName = project->values("QMAKE_TARGET_COMPANY").join(" ");
+
+ QString description;
+ if (!project->values("QMAKE_TARGET_DESCRIPTION").isEmpty())
+ description = project->values("QMAKE_TARGET_DESCRIPTION").join(" ");
+
+ QString copyright;
+ if (!project->values("QMAKE_TARGET_COPYRIGHT").isEmpty())
+ copyright = project->values("QMAKE_TARGET_COPYRIGHT").join(" ");
+
+ QString productName;
+ if (!project->values("QMAKE_TARGET_PRODUCT").isEmpty())
+ productName = project->values("QMAKE_TARGET_PRODUCT").join(" ");
+ else
+ productName = project->values("TARGET").first();
+
+ QString originalName = project->values("TARGET").first() + project->values("TARGET_EXT").first();
+
+ ts << "# if defined(UNDER_CE)" << endl;
+ ts << "# include <winbase.h>" << endl;
+ ts << "# else" << endl;
+ ts << "# include <winver.h>" << endl;
+ ts << "# endif" << endl;
+ ts << endl;
+ ts << "VS_VERSION_INFO VERSIONINFO" << endl;
+ ts << "\tFILEVERSION " << QString(versionString).replace(".", ",") << endl;
+ ts << "\tPRODUCTVERSION " << QString(versionString).replace(".", ",") << endl;
+ ts << "\tFILEFLAGSMASK 0x3fL" << endl;
+ ts << "#ifdef _DEBUG" << endl;
+ ts << "\tFILEFLAGS VS_FF_DEBUG" << endl;
+ ts << "#else" << endl;
+ ts << "\tFILEFLAGS 0x0L" << endl;
+ ts << "#endif" << endl;
+ ts << "\tFILEOS VOS__WINDOWS32" << endl;
+ if (project->isActiveConfig("shared"))
+ ts << "\tFILETYPE VFT_DLL" << endl;
+ else
+ ts << "\tFILETYPE VFT_APP" << endl;
+ ts << "\tFILESUBTYPE 0x0L" << endl;
+ ts << "\tBEGIN" << endl;
+ ts << "\t\tBLOCK \"StringFileInfo\"" << endl;
+ ts << "\t\tBEGIN" << endl;
+ ts << "\t\t\tBLOCK \"040904B0\"" << endl;
+ ts << "\t\t\tBEGIN" << endl;
+ ts << "\t\t\t\tVALUE \"CompanyName\", \"" << companyName << "\\0\"" << endl;
+ ts << "\t\t\t\tVALUE \"FileDescription\", \"" << description << "\\0\"" << endl;
+ ts << "\t\t\t\tVALUE \"FileVersion\", \"" << versionString << "\\0\"" << endl;
+ ts << "\t\t\t\tVALUE \"LegalCopyright\", \"" << copyright << "\\0\"" << endl;
+ ts << "\t\t\t\tVALUE \"OriginalFilename\", \"" << originalName << "\\0\"" << endl;
+ ts << "\t\t\t\tVALUE \"ProductName\", \"" << productName << "\\0\"" << endl;
+ ts << "\t\t\tEND" << endl;
+ ts << "\t\tEND" << endl;
+ ts << "\t\tBLOCK \"VarFileInfo\"" << endl;
+ ts << "\t\tBEGIN" << endl;
+ ts << "\t\t\tVALUE \"Translation\", 0x409, 1200" << endl;
+ ts << "\t\tEND" << endl;
+ ts << "\tEND" << endl;
+ ts << "/* End of Version info */" << endl;
+ ts << endl;
+
+ ts.flush();
+
+
+ QString rcFilename = project->values("OUT_PWD").first()
+ + "/"
+ + project->values("TARGET").first()
+ + "_resource"
+ + ".rc";
+ QFile rcFile(QDir::cleanPath(rcFilename));
+
+ bool writeRcFile = true;
+ if (rcFile.exists() && rcFile.open(QFile::ReadOnly)) {
+ writeRcFile = rcFile.readAll() != rcString;
+ rcFile.close();
+ }
+ if (writeRcFile) {
+ bool ok;
+ ok = rcFile.open(QFile::WriteOnly);
+ if (!ok) {
+ // The file can't be opened... try creating the containing
+ // directory first (needed for clean shadow builds)
+ QDir().mkpath(QFileInfo(rcFile).path());
+ ok = rcFile.open(QFile::WriteOnly);
+ }
+ if (!ok) {
+ ::fprintf(stderr, "Cannot open for writing: %s", rcFile.fileName().toLatin1().constData());
+ ::exit(1);
+ }
+ rcFile.write(rcString);
+ rcFile.close();
+ }
+ if (project->values("QMAKE_WRITE_DEFAULT_RC").isEmpty())
+ project->values("RC_FILE").insert(0, rcFile.fileName());
+ }
+ if (!project->values("RC_FILE").isEmpty()) {
+ if (!project->values("RES_FILE").isEmpty()) {
+ fprintf(stderr, "Both rc and res file specified.\n");
+ fprintf(stderr, "Please specify one of them, not both.");
+ exit(1);
+ }
+ QString resFile = project->values("RC_FILE").first();
+
+ // if this is a shadow build then use the absolute path of the rc file
+ if (Option::output_dir != qmake_getpwd()) {
+ QFileInfo fi(resFile);
+ project->values("RC_FILE").first() = fi.absoluteFilePath();
+ }
+
+ resFile.replace(".rc", Option::res_ext);
+ project->values("RES_FILE").prepend(fileInfo(resFile).fileName());
+ if (!project->values("OBJECTS_DIR").isEmpty()) {
+ QString resDestDir;
+ if (project->isActiveConfig("staticlib"))
+ resDestDir = fileInfo(project->first("DESTDIR")).absoluteFilePath();
+ else
+ resDestDir = project->first("OBJECTS_DIR");
+ resDestDir.append(Option::dir_sep);
+ project->values("RES_FILE").first().prepend(resDestDir);
+ }
+ project->values("RES_FILE").first() = Option::fixPathToTargetOS(project->values("RES_FILE").first(), false, false);
+ project->values("POST_TARGETDEPS") += project->values("RES_FILE");
+ project->values("CLEAN_FILES") += project->values("RES_FILE");
+ }
+}
+
+void Win32MakefileGenerator::processFileTagsVar()
+{
+ QStringList tags;
+ tags << "SOURCES" << "GENERATED_SOURCES" << "DEF_FILE" << "RC_FILE"
+ << "TARGET" << "QMAKE_LIBS" << "DESTDIR" << "DLLDESTDIR" << "INCLUDEPATH";
+ if(!project->isEmpty("QMAKE_EXTRA_COMPILERS")) {
+ const QStringList &quc = project->values("QMAKE_EXTRA_COMPILERS");
+ for(QStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it)
+ tags += project->values((*it)+".input");
+ }
+
+ //clean path
+ QStringList &filetags = project->values("QMAKE_FILETAGS");
+ for(int i = 0; i < tags.size(); ++i)
+ filetags += Option::fixPathToTargetOS(tags.at(i), false);
+}
+
+void Win32MakefileGenerator::writeCleanParts(QTextStream &t)
+{
+ t << "clean: compiler_clean " << var("CLEAN_DEPS");
+ {
+ const char *clean_targets[] = { "OBJECTS", "QMAKE_CLEAN", "CLEAN_FILES", 0 };
+ for(int i = 0; clean_targets[i]; ++i) {
+ const QStringList &list = project->values(clean_targets[i]);
+ const QString del_statement("-$(DEL_FILE)");
+ if(project->isActiveConfig("no_delete_multiple_files")) {
+ for(QStringList::ConstIterator it = list.begin(); it != list.end(); ++it)
+ t << "\n\t" << del_statement << " " << escapeFilePath((*it));
+ } else {
+ QString files, file;
+ const int commandlineLimit = 2047; // NT limit, expanded
+ for(QStringList::ConstIterator it = list.begin(); it != list.end(); ++it) {
+ file = " " + escapeFilePath((*it));
+ if(del_statement.length() + files.length() +
+ qMax(fixEnvVariables(file).length(), file.length()) > commandlineLimit) {
+ t << "\n\t" << del_statement << files;
+ files.clear();
+ }
+ files += file;
+ }
+ if(!files.isEmpty())
+ t << "\n\t" << del_statement << files;
+ }
+ }
+ }
+ t << endl << endl;
+
+ t << "distclean: clean";
+ {
+ const char *clean_targets[] = { "QMAKE_DISTCLEAN", 0 };
+ for(int i = 0; clean_targets[i]; ++i) {
+ const QStringList &list = project->values(clean_targets[i]);
+ const QString del_statement("-$(DEL_FILE)");
+ if(project->isActiveConfig("no_delete_multiple_files")) {
+ for(QStringList::ConstIterator it = list.begin(); it != list.end(); ++it)
+ t << "\n\t" << del_statement << " " << escapeFilePath((*it));
+ } else {
+ QString files, file;
+ const int commandlineLimit = 2047; // NT limit, expanded
+ for(QStringList::ConstIterator it = list.begin(); it != list.end(); ++it) {
+ file = " " + escapeFilePath((*it));
+ if(del_statement.length() + files.length() +
+ qMax(fixEnvVariables(file).length(), file.length()) > commandlineLimit) {
+ t << "\n\t" << del_statement << files;
+ files.clear();
+ }
+ files += file;
+ }
+ if(!files.isEmpty())
+ t << "\n\t" << del_statement << files;
+ }
+ }
+ }
+ t << "\n\t-$(DEL_FILE) $(DESTDIR_TARGET)" << endl;
+ {
+ QString ofile = Option::fixPathToTargetOS(fileFixify(Option::output.fileName()));
+ if(!ofile.isEmpty())
+ t << "\t-$(DEL_FILE) " << ofile << endl;
+ }
+ t << endl;
+}
+
+void Win32MakefileGenerator::writeIncPart(QTextStream &t)
+{
+ t << "INCPATH = ";
+
+ const QStringList &incs = project->values("INCLUDEPATH");
+ for(int i = 0; i < incs.size(); ++i) {
+ QString inc = incs.at(i);
+ inc.replace(QRegExp("\\\\$"), "");
+ inc.replace(QRegExp("\""), "");
+ if(!inc.isEmpty())
+ t << "-I" << "\"" << inc << "\" ";
+ }
+ t << "-I\"" << specdir() << "\""
+ << endl;
+}
+
+void Win32MakefileGenerator::writeStandardParts(QTextStream &t)
+{
+ t << "####### Compiler, tools and options" << endl << endl;
+ t << "CC = " << var("QMAKE_CC") << endl;
+ t << "CXX = " << var("QMAKE_CXX") << endl;
+ t << "DEFINES = "
+ << varGlue("PRL_EXPORT_DEFINES","-D"," -D"," ")
+ << varGlue("DEFINES","-D"," -D","") << endl;
+ t << "CFLAGS = " << var("QMAKE_CFLAGS") << " $(DEFINES)" << endl;
+ t << "CXXFLAGS = " << var("QMAKE_CXXFLAGS") << " $(DEFINES)" << endl;
+
+ writeIncPart(t);
+ writeLibsPart(t);
+
+ t << "QMAKE = " << var("QMAKE_QMAKE") << endl;
+ t << "IDC = " << (project->isEmpty("QMAKE_IDC") ? QString("idc") :
+ Option::fixPathToTargetOS(var("QMAKE_IDC"), false)) << endl;
+ t << "IDL = " << (project->isEmpty("QMAKE_IDL") ? QString("midl") :
+ Option::fixPathToTargetOS(var("QMAKE_IDL"), false)) << endl;
+ t << "ZIP = " << var("QMAKE_ZIP") << endl;
+ t << "DEF_FILE = " << varList("DEF_FILE") << endl;
+ t << "RES_FILE = " << varList("RES_FILE") << endl; // Not on mingw, can't see why not though...
+ t << "COPY = " << var("QMAKE_COPY") << endl;
+ t << "COPY_FILE = " << var("QMAKE_COPY_FILE") << endl;
+ t << "COPY_DIR = " << var("QMAKE_COPY_DIR") << endl;
+ t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl;
+ t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl;
+ t << "MOVE = " << var("QMAKE_MOVE") << endl;
+ t << "CHK_DIR_EXISTS= " << var("QMAKE_CHK_DIR_EXISTS") << endl;
+ t << "MKDIR = " << var("QMAKE_MKDIR") << endl;
+ t << "INSTALL_FILE = " << var("QMAKE_INSTALL_FILE") << endl;
+ t << "INSTALL_PROGRAM = " << var("QMAKE_INSTALL_PROGRAM") << endl;
+ t << "INSTALL_DIR = " << var("QMAKE_INSTALL_DIR") << endl;
+ t << endl;
+
+ t << "####### Output directory" << endl << endl;
+ if(!project->values("OBJECTS_DIR").isEmpty())
+ t << "OBJECTS_DIR = " << var("OBJECTS_DIR").replace(QRegExp("\\\\$"),"") << endl;
+ else
+ t << "OBJECTS_DIR = . " << endl;
+ t << endl;
+
+ t << "####### Files" << endl << endl;
+ t << "SOURCES = " << valList(escapeFilePaths(project->values("SOURCES")))
+ << " " << valList(escapeFilePaths(project->values("GENERATED_SOURCES"))) << endl;
+
+ // do this here so we can set DEST_TARGET to be the complete path to the final target if it is needed.
+ QString orgDestDir = var("DESTDIR");
+ QString destDir = Option::fixPathToTargetOS(orgDestDir, false);
+ if (!destDir.isEmpty() && (orgDestDir.endsWith('/') || orgDestDir.endsWith(Option::dir_sep)))
+ destDir += Option::dir_sep;
+ QString target = QString(project->first("TARGET")+project->first("TARGET_EXT"));
+ target.remove("\"");
+ project->values("DEST_TARGET").prepend(destDir + target);
+
+ writeObjectsPart(t);
+
+ writeExtraCompilerVariables(t);
+ writeExtraVariables(t);
+
+ t << "DIST = " << varList("DISTFILES") << endl;
+ t << "QMAKE_TARGET = " << var("QMAKE_ORIG_TARGET") << endl;
+ // The comment is important to maintain variable compatibility with Unix
+ // Makefiles, while not interpreting a trailing-slash as a linebreak
+ t << "DESTDIR = " << escapeFilePath(destDir) << " #avoid trailing-slash linebreak" << endl;
+ t << "TARGET = " << escapeFilePath(target) << endl;
+ t << "DESTDIR_TARGET = " << escapeFilePath(var("DEST_TARGET")) << endl;
+ t << endl;
+
+ t << "####### Implicit rules" << endl << endl;
+ writeImplicitRulesPart(t);
+
+ t << "####### Build rules" << endl << endl;
+ writeBuildRulesPart(t);
+
+ if(project->isActiveConfig("shared") && !project->values("DLLDESTDIR").isEmpty()) {
+ QStringList dlldirs = project->values("DLLDESTDIR");
+ for (QStringList::Iterator dlldir = dlldirs.begin(); dlldir != dlldirs.end(); ++dlldir) {
+ t << "\t" << "-$(COPY_FILE) \"$(DESTDIR_TARGET)\" " << Option::fixPathToTargetOS(*dlldir, false) << endl;
+ }
+ }
+ t << endl;
+
+ writeRcFilePart(t);
+
+ writeMakeQmake(t);
+
+ QStringList dist_files = fileFixify(Option::mkfile::project_files);
+ if(!project->isEmpty("QMAKE_INTERNAL_INCLUDED_FILES"))
+ dist_files += project->values("QMAKE_INTERNAL_INCLUDED_FILES");
+ if(!project->isEmpty("TRANSLATIONS"))
+ dist_files << var("TRANSLATIONS");
+ if(!project->isEmpty("FORMS")) {
+ QStringList &forms = project->values("FORMS");
+ for(QStringList::Iterator formit = forms.begin(); formit != forms.end(); ++formit) {
+ QString ui_h = fileFixify((*formit) + Option::h_ext.first());
+ if(exists(ui_h))
+ dist_files << ui_h;
+ }
+ }
+ t << "dist:" << "\n\t"
+ << "$(ZIP) " << var("QMAKE_ORIG_TARGET") << ".zip " << "$(SOURCES) $(DIST) "
+ << dist_files.join(" ") << " " << var("TRANSLATIONS") << " ";
+ if(!project->isEmpty("QMAKE_EXTRA_COMPILERS")) {
+ const QStringList &quc = project->values("QMAKE_EXTRA_COMPILERS");
+ for(QStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) {
+ const QStringList &inputs = project->values((*it)+".input");
+ for(QStringList::ConstIterator input = inputs.begin(); input != inputs.end(); ++input) {
+ t << (*input) << " ";
+ }
+ }
+ }
+ t << endl << endl;
+
+ writeCleanParts(t);
+ writeExtraTargets(t);
+ writeExtraCompilerTargets(t);
+ t << endl << endl;
+}
+
+void Win32MakefileGenerator::writeLibsPart(QTextStream &t)
+{
+ if(project->isActiveConfig("staticlib") && project->first("TEMPLATE") == "lib") {
+ t << "LIBAPP = " << var("QMAKE_LIB") << endl;
+ t << "LIBFLAGS = " << var("QMAKE_LIBFLAGS") << endl;
+ } else {
+ t << "LINK = " << var("QMAKE_LINK") << endl;
+ t << "LFLAGS = ";
+ if(!project->values("QMAKE_LIBDIR").isEmpty())
+ writeLibDirPart(t);
+ t << var("QMAKE_LFLAGS") << endl;
+ t << "LIBS = " << var("QMAKE_LIBS") << " " << var("QMAKE_LIBS_PRIVATE") << endl;
+ }
+}
+
+void Win32MakefileGenerator::writeLibDirPart(QTextStream &t)
+{
+ QStringList libDirs = project->values("QMAKE_LIBDIR");
+ for (int i = 0; i < libDirs.size(); ++i)
+ libDirs[i].remove("\"");
+ t << valGlue(libDirs,"-L\"","\" -L\"","\"") << " ";
+}
+
+void Win32MakefileGenerator::writeObjectsPart(QTextStream &t)
+{
+ t << "OBJECTS = " << valList(escapeDependencyPaths(project->values("OBJECTS"))) << endl;
+}
+
+void Win32MakefileGenerator::writeImplicitRulesPart(QTextStream &t)
+{
+ t << ".SUFFIXES:";
+ for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit)
+ t << " " << (*cppit);
+ for(QStringList::Iterator cit = Option::c_ext.begin(); cit != Option::c_ext.end(); ++cit)
+ t << " " << (*cit);
+ t << endl << endl;
+ for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit)
+ t << (*cppit) << Option::obj_ext << ":\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl;
+ for(QStringList::Iterator cit = Option::c_ext.begin(); cit != Option::c_ext.end(); ++cit)
+ t << (*cit) << Option::obj_ext << ":\n\t" << var("QMAKE_RUN_CC_IMP") << endl << endl;
+}
+
+void Win32MakefileGenerator::writeBuildRulesPart(QTextStream &)
+{
+}
+
+void Win32MakefileGenerator::writeRcFilePart(QTextStream &t)
+{
+ if(!project->values("RC_FILE").isEmpty()) {
+ const QString res_file = project->first("RES_FILE"),
+ rc_file = fileFixify(project->first("RC_FILE"));
+ // The resource tool needs to have the same defines passed in as the compiler, since you may
+ // use these defines in the .rc file itself. Also, we need to add the _DEBUG define manually
+ // since the compiler defines this symbol by itself, and we use it in the automatically
+ // created rc file when VERSION is define the .pro file.
+ t << res_file << ": " << rc_file << "\n\t"
+ << var("QMAKE_RC") << (project->isActiveConfig("debug") ? " -D_DEBUG" : "") << " $(DEFINES) -fo " << res_file << " " << rc_file;
+ t << endl << endl;
+ }
+}
+
+QString Win32MakefileGenerator::getLibTarget()
+{
+ return QString(project->first("TARGET") + project->first("TARGET_VERSION_EXT") + ".lib");
+}
+
+QString Win32MakefileGenerator::defaultInstall(const QString &t)
+{
+ if((t != "target" && t != "dlltarget") ||
+ (t == "dlltarget" && (project->first("TEMPLATE") != "lib" || !project->isActiveConfig("shared"))) ||
+ project->first("TEMPLATE") == "subdirs")
+ return QString();
+
+ const QString root = "$(INSTALL_ROOT)";
+ QStringList &uninst = project->values(t + ".uninstall");
+ QString ret;
+ QString targetdir = Option::fixPathToTargetOS(project->first(t + ".path"), false);
+ targetdir = fileFixify(targetdir, FileFixifyAbsolute);
+ if(targetdir.right(1) != Option::dir_sep)
+ targetdir += Option::dir_sep;
+
+ if(t == "target" && project->first("TEMPLATE") == "lib") {
+ if(project->isActiveConfig("create_prl") && !project->isActiveConfig("no_install_prl") &&
+ !project->isEmpty("QMAKE_INTERNAL_PRL_FILE")) {
+ QString dst_prl = Option::fixPathToTargetOS(project->first("QMAKE_INTERNAL_PRL_FILE"));
+ int slsh = dst_prl.lastIndexOf(Option::dir_sep);
+ if(slsh != -1)
+ dst_prl = dst_prl.right(dst_prl.length() - slsh - 1);
+ dst_prl = filePrefixRoot(root, targetdir + dst_prl);
+ ret += "-$(INSTALL_FILE) \"" + project->first("QMAKE_INTERNAL_PRL_FILE") + "\" \"" + dst_prl + "\"";
+ if(!uninst.isEmpty())
+ uninst.append("\n\t");
+ uninst.append("-$(DEL_FILE) \"" + dst_prl + "\"");
+ }
+ if(project->isActiveConfig("create_pc")) {
+ QString dst_pc = pkgConfigFileName(false);
+ if (!dst_pc.isEmpty()) {
+ dst_pc = filePrefixRoot(root, targetdir + dst_pc);
+ if(!ret.isEmpty())
+ ret += "\n\t";
+ ret += "-$(INSTALL_FILE) \"" + pkgConfigFileName(true) + "\" \"" + dst_pc + "\"";
+ if(!uninst.isEmpty())
+ uninst.append("\n\t");
+ uninst.append("-$(DEL_FILE) \"" + dst_pc + "\"");
+ }
+ }
+ if(project->isActiveConfig("shared") && !project->isActiveConfig("plugin")) {
+ QString lib_target = getLibTarget();
+ lib_target.remove('"');
+ QString src_targ = (project->isEmpty("DESTDIR") ? QString("$(DESTDIR)") : project->first("DESTDIR")) + lib_target;
+ QString dst_targ = filePrefixRoot(root, fileFixify(targetdir + lib_target, FileFixifyAbsolute));
+ if(!ret.isEmpty())
+ ret += "\n\t";
+ ret += QString("-$(INSTALL_FILE)") + " \"" + src_targ + "\" \"" + dst_targ + "\"";
+ if(!uninst.isEmpty())
+ uninst.append("\n\t");
+ uninst.append("-$(DEL_FILE) \"" + dst_targ + "\"");
+ }
+ }
+
+ if(t == "dlltarget" || project->values(t + ".CONFIG").indexOf("no_dll") == -1) {
+ QString src_targ = "$(DESTDIR_TARGET)";
+ QString dst_targ = filePrefixRoot(root, fileFixify(targetdir + "$(TARGET)", FileFixifyAbsolute));
+ if(!ret.isEmpty())
+ ret += "\n\t";
+ ret += QString("-$(INSTALL_FILE)") + " \"" + src_targ + "\" \"" + dst_targ + "\"";
+ if(!uninst.isEmpty())
+ uninst.append("\n\t");
+ uninst.append("-$(DEL_FILE) \"" + dst_targ + "\"");
+ }
+ return ret;
+}
+
+QString Win32MakefileGenerator::escapeFilePath(const QString &path) const
+{
+ QString ret = path;
+ if(!ret.isEmpty()) {
+ ret = unescapeFilePath(ret);
+ if(ret.contains(" "))
+ ret = "\"" + ret + "\"";
+ debug_msg(2, "EscapeFilePath: %s -> %s", path.toLatin1().constData(), ret.toLatin1().constData());
+ }
+ return ret;
+}
+
+QT_END_NAMESPACE
diff --git a/qmake/generators/win32/winmakefile.h b/qmake/generators/win32/winmakefile.h
new file mode 100644
index 0000000000..fb11e1ae9d
--- /dev/null
+++ b/qmake/generators/win32/winmakefile.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the qmake application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef WINMAKEFILE_H
+#define WINMAKEFILE_H
+
+#include "makefile.h"
+
+QT_BEGIN_NAMESPACE
+
+// In the Qt evaluation and educational version, we have a postfix in the
+// library name (e.g. qtmteval301.dll). QTDLL_POSTFIX is used for this.
+// A script modifies these lines when building eval/edu version, so be careful
+// when changing them.
+#ifndef QTDLL_POSTFIX
+#define QTDLL_POSTFIX ""
+#endif
+
+class Win32MakefileGenerator : public MakefileGenerator
+{
+public:
+ Win32MakefileGenerator();
+ ~Win32MakefileGenerator();
+protected:
+ virtual QString defaultInstall(const QString &);
+ virtual void writeCleanParts(QTextStream &t);
+ virtual void writeStandardParts(QTextStream &t);
+ virtual void writeIncPart(QTextStream &t);
+ virtual void writeLibDirPart(QTextStream &t);
+ virtual void writeLibsPart(QTextStream &t);
+ virtual void writeObjectsPart(QTextStream &t);
+ virtual void writeImplicitRulesPart(QTextStream &t);
+ virtual void writeBuildRulesPart(QTextStream &);
+ virtual QString escapeFilePath(const QString &path) const;
+
+ virtual void writeRcFilePart(QTextStream &t);
+
+ int findHighestVersion(const QString &dir, const QString &stem, const QString &ext = QLatin1String("lib"));
+ bool findLibraries(const QString &);
+ virtual bool findLibraries();
+
+ virtual void processPrlFiles();
+ virtual void processVars();
+ virtual void fixTargetExt();
+ virtual void processRcFileVar();
+ virtual void processFileTagsVar();
+ virtual QString getLibTarget();
+};
+
+inline Win32MakefileGenerator::~Win32MakefileGenerator()
+{ }
+
+inline bool Win32MakefileGenerator::findLibraries()
+{ return findLibraries("QMAKE_LIBS") && findLibraries("QMAKE_LIBS_PRIVATE"); }
+
+QT_END_NAMESPACE
+
+#endif // WINMAKEFILE_H