summaryrefslogtreecommitdiffstats
path: root/qmake/generators/win32
diff options
context:
space:
mode:
Diffstat (limited to 'qmake/generators/win32')
-rw-r--r--qmake/generators/win32/borland_bmake.cpp177
-rw-r--r--qmake/generators/win32/borland_bmake.h68
-rw-r--r--qmake/generators/win32/mingw_make.cpp460
-rw-r--r--qmake/generators/win32/mingw_make.h87
-rw-r--r--qmake/generators/win32/msvc_dsp.cpp1207
-rw-r--r--qmake/generators/win32/msvc_dsp.h122
-rw-r--r--qmake/generators/win32/msvc_nmake.cpp322
-rw-r--r--qmake/generators/win32/msvc_nmake.h76
-rw-r--r--qmake/generators/win32/msvc_objectmodel.cpp2636
-rw-r--r--qmake/generators/win32/msvc_objectmodel.h1078
-rw-r--r--qmake/generators/win32/msvc_vcproj.cpp1785
-rw-r--r--qmake/generators/win32/msvc_vcproj.h152
-rw-r--r--qmake/generators/win32/winmakefile.cpp821
-rw-r--r--qmake/generators/win32/winmakefile.h96
14 files changed, 9087 insertions, 0 deletions
diff --git a/qmake/generators/win32/borland_bmake.cpp b/qmake/generators/win32/borland_bmake.cpp
new file mode 100644
index 0000000..411c7ab
--- /dev/null
+++ b/qmake/generators/win32/borland_bmake.cpp
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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");
+ if(project->values("QMAKE_QMAKE").isEmpty())
+ project->values("QMAKE_QMAKE").append("qmake");
+ 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 0000000..46c7d0a
--- /dev/null
+++ b/qmake/generators/win32/borland_bmake.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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 0000000..7473b10
--- /dev/null
+++ b/qmake/generators/win32/mingw_make.cpp
@@ -0,0 +1,460 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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()
+{
+ QStringList &l = project->values("QMAKE_LIBS");
+
+ 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(Option::mkfile::do_stub_makefile) {
+ t << "QMAKE = " << (project->isEmpty("QMAKE_QMAKE") ? QString("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) {
+ if (QDir::isRelativePath(*it))
+ t << "ADDMOD " << *it << endl;
+ else
+ t << *it << endl;
+ }
+ t << "SAVE" << endl;
+ t.flush();
+ file.close();
+ }
+}
+
+void MingwMakefileGenerator::writeMingwParts(QTextStream &t)
+{
+ 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");
+ if(project->values("QMAKE_QMAKE").isEmpty())
+ project->values("QMAKE_QMAKE").append("qmake");
+ 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"));
+
+ 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")) {
+ 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_LFLAGS").append(QString("-Wl,") + project->first("DEF_FILE"));
+
+ 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("TARGET_EXT").append(".a");
+ project->values("QMAKE_LFLAGS").append("-static");
+ project->values("TARGET").first() = "lib" + project->first("TARGET");
+ } else {
+ 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);
+ t << var("QMAKE_LIBS").replace(QRegExp("(\\slib|^lib)")," -l") << endl;
+ }
+}
+
+void MingwMakefileGenerator::writeLibDirPart(QTextStream &t)
+{
+ QStringList libDirs = project->values("QMAKE_LIBDIR");
+ for (int i = 0; i < libDirs.size(); ++i)
+ libDirs[i].remove("\"");
+ t << valGlue(libDirs,"-L"+quote,quote+" -L" +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");
+ }
+ createArObjectScriptFile(ar_script_file, var("DEST_TARGET"), project->values("OBJECTS"));
+ objectsLinkLine = "ar -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");
+ }
+ 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 << 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 0000000..1c394b2
--- /dev/null
+++ b/qmake/generators/win32/mingw_make.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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();
+private:
+ bool isWindowsShell() const;
+ void writeMingwParts(QTextStream &);
+ void writeIncPart(QTextStream &t);
+ void writeLibsPart(QTextStream &t);
+ void writeLibDirPart(QTextStream &t);
+ bool writeMakefile(QTextStream &);
+ void writeObjectsPart(QTextStream &t);
+ void writeBuildRulesPart(QTextStream &t);
+ void writeRcFilePart(QTextStream &t);
+ void init();
+ void processPrlVariable(const QString &var, const QStringList &l);
+
+ QStringList &findDependencies(const QString &file);
+
+ QString preCompHeaderOut;
+
+ virtual bool findLibraries();
+ 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/msvc_dsp.cpp b/qmake/generators/win32/msvc_dsp.cpp
new file mode 100644
index 0000000..17a5154
--- /dev/null
+++ b/qmake/generators/win32/msvc_dsp.cpp
@@ -0,0 +1,1207 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "msvc_dsp.h"
+#include "option.h"
+
+#include <qdir.h>
+#include <qset.h>
+
+#include <stdlib.h>
+
+QT_BEGIN_NAMESPACE
+
+DspMakefileGenerator::DspMakefileGenerator() : Win32MakefileGenerator(), init_flag(false)
+{
+}
+
+bool DspMakefileGenerator::writeMakefile(QTextStream &t)
+{
+ if(!project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty()) {
+ /* for now just dump, I need to generated an empty dsp or something.. */
+ fprintf(stderr, "Project file not generated because all requirements not met:\n\t%s\n",
+ var("QMAKE_FAILED_REQUIREMENTS").toLatin1().constData());
+ return true;
+ }
+
+ // Generate workspace file
+ if(project->first("TEMPLATE") == "vcsubdirs") {
+ if (!project->isActiveConfig("build_pass")) {
+ debug_msg(1, "Generator: MSVC: Writing workspave file");
+ writeSubDirs(t);
+ } else {
+ debug_msg(1, "Generator: MSVC: Not writing workspace file for build_pass configs");
+ }
+ return true;
+ } else if (project->first("TEMPLATE") == "vcapp" || project->first("TEMPLATE") == "vclib") {
+ if(!project->isActiveConfig("build_pass"))
+ return writeDspParts(t);
+ return true;
+ }
+ return project->isActiveConfig("build_pass");
+}
+
+bool DspMakefileGenerator::hasBuiltinCompiler(const QString &filename) const
+{
+ for (int i = 0; i < Option::cpp_ext.count(); ++i)
+ if (filename.endsWith(Option::cpp_ext.at(i)))
+ return true;
+ for (int i = 0; i < Option::c_ext.count(); ++i)
+ if (filename.endsWith(Option::c_ext.at(i)))
+ return true;
+ return false;
+}
+
+QString DspMakefileGenerator::replaceExtraCompilerVariables(const QString &var, const QStringList &in, const QStringList &out)
+{
+ QString ret = MakefileGenerator::replaceExtraCompilerVariables(var, in, out);
+ ret.replace("$(DEFINES)", varGlue("PRL_EXPORT_DEFINES"," -D"," -D","") +
+ varGlue("DEFINES"," -D"," -D",""));
+
+ QString incpath = this->var("MSVCDSP_INCPATH");
+ incpath.replace("/I", "-I");
+ ret.replace("$(INCPATH)", incpath);
+ return ret;
+}
+
+
+// if config is part of a multibuild thenthe gule (this) has the correct MSVCDSP_PROJECT
+QString DspMakefileGenerator::configName(DspMakefileGenerator * config)
+{
+ return var("MSVCDSP_PROJECT") + config->var("MSVCDSP_CONFIG_NAME");
+}
+
+bool DspMakefileGenerator::writeDspHeader(QTextStream &t)
+{
+ DspMakefileGenerator * config = this;
+ if (mergedProjects.count())
+ config = mergedProjects.at(0);
+
+ t << "# Microsoft Developer Studio Project File - Name=\"" << var("MSVCDSP_PROJECT") << "\" - Package Owner=<4>" << endl;
+ t << "# Microsoft Developer Studio Generated Build File, Format Version 6.00" << endl;
+ t << "# ** DO NOT EDIT **" << endl;
+ t << endl;
+ t << "# TARGTYPE \"Win32 (x86) " << var("MSVCDSP_TARGETTYPE") << "\" " << var("MSVCDSP_DSPTYPE") << endl;
+ t << endl;
+ t << "CFG=\"" << configName(config) << "\"" << endl;
+ t << "!MESSAGE This is not a valid makefile. To build this project using NMAKE," << endl;
+ t << "!MESSAGE use the Export Makefile command and run" << endl;
+ t << "!MESSAGE " << endl;
+ t << "!MESSAGE NMAKE /f " << escapeFilePath(var("TARGET")) << ".mak." << endl;
+ t << "!MESSAGE " << endl;
+ t << "!MESSAGE You can specify a configuration when running NMAKE" << endl;
+ t << "!MESSAGE by defining the macro CFG on the command line. For example:" << endl;
+ t << "!MESSAGE " << endl;
+ t << "!MESSAGE NMAKE /f " << escapeFilePath(var("TARGET")) << ".mak CFG=\"" << configName(config) << "\"" << endl;
+ t << "!MESSAGE " << endl;
+ t << "!MESSAGE Possible choices for configuration are:" << endl;
+ t << "!MESSAGE " << endl;
+ if (mergedProjects.count()) {
+ for (int i = 0; i < mergedProjects.count(); ++i) {
+ DspMakefileGenerator * config = mergedProjects.at(i);
+ t << "!MESSAGE \"" << configName(config) << "\" (based on \"Win32 (x86) " << config->var("MSVCDSP_TARGETTYPE") << "\")" << endl;
+ }
+ } else {
+ t << "!MESSAGE \"" << configName(config) << "\" (based on \"Win32 (x86) " << config->var("MSVCDSP_TARGETTYPE") << "\")" << endl;
+ }
+ t << "!MESSAGE " << endl;
+ t << endl;
+ t << "# Begin Project" << endl;
+ t << "# PROP AllowPerConfigDependencies 0" << endl;
+ t << "# PROP Scc_ProjName \"\"" << endl;
+ t << "# PROP Scc_LocalPath \"\"" << endl;
+ t << "CPP=" << config->var("QMAKE_CC") << endl;
+ t << "MTL=" << config->var("QMAKE_IDL") << endl;
+ t << "RSC=" << config->var("QMAKE_RC") << endl;
+ t << "BSC32=bscmake.exe" << endl;
+
+ return true;
+}
+
+
+bool DspMakefileGenerator::writeDspParts(QTextStream &t)
+{
+ //bool staticLibTarget = var("MSVCDSP_DSPTYPE") == "0x0104";
+
+ writeDspHeader(t);
+ writeDspConfig(t, this);
+ t << endl;
+ t << "# Begin Target" << endl;
+ t << endl;
+ t << "# Name \"" << configName(this) << "\"" << endl;
+ t << endl;
+
+
+ QStringList listNames = QString("SOURCES|DEF_FILE").split("|");
+ QStringList allListNames = listNames;
+ writeFileGroup(t, listNames, "Source Files", "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat");
+ listNames = QStringList("HEADERS");
+ allListNames += listNames;
+ writeFileGroup(t, QStringList("HEADERS"), "Header Files", "h;hpp;hxx;hm;inl");
+ listNames = QString("FORMS|INTERFACES|FORMS3").split("|");
+ allListNames += listNames;
+ writeFileGroup(t, listNames, "Form Files", "ui");
+ listNames = QStringList("IMAGES");
+ allListNames += listNames;
+ writeFileGroup(t, QStringList("IMAGES"), "Image Files", "");
+ listNames = QString("RC_FILE|RESOURCES").split("|");
+ allListNames += listNames;
+ writeFileGroup(t, listNames, "Resources", "rc;qrc");
+ listNames = QStringList("TRANSLATIONS");
+ allListNames += listNames;
+ writeFileGroup(t, listNames, "Translations", "ts;xlf");
+ listNames = QStringList("LEXSOURCES");
+ allListNames += listNames;
+ writeFileGroup(t, listNames, "Lexables", "l");
+ listNames = QStringList("YACCSOURCES");
+ allListNames += listNames;
+ writeFileGroup(t, listNames, "Yaccables", "y");
+ listNames = QStringList("TYPELIBS");
+ allListNames += listNames;
+ writeFileGroup(t, listNames, "Type Libraries", "tlb;olb");
+
+ 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) {
+ if (!allListNames.contains((*input)) && *input != "UIC3_HEADERS")
+ writeFileGroup(t, QStringList((*input)), (*input) + " Files", "");
+ }
+ }
+ }
+
+ project->values("SWAPPED_BUILD_STEPS") = swappedBuildSteps.keys();
+
+ writeFileGroup(t, QString("GENERATED_SOURCES|GENERATED_FILES|SWAPPED_BUILD_STEPS").split("|"), "Generated", "");
+
+ t << "# End Target" << endl;
+ t << "# End Project" << endl;
+ return true;
+}
+
+void
+DspMakefileGenerator::init()
+{
+ if(init_flag)
+ return;
+ QStringList::Iterator it;
+ init_flag = true;
+
+ platform = "Win32";
+ if(!project->values("QMAKE_PLATFORM").isEmpty())
+ platform = varGlue("QMAKE_PLATFORM", "", " ", "");
+
+ // 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"));
+
+ project->values("QMAKE_LIBS") += escapeFilePaths(project->values("LIBS"));
+ processVars();
+
+ if(!project->values("VERSION").isEmpty()) {
+ QString version = project->values("VERSION").first();
+ int firstDot = version.indexOf(".");
+ QString major = version.left(firstDot);
+ QString minor = version.right(version.length() - firstDot - 1);
+ minor.replace(".", "");
+ project->values("MSVCDSP_LFLAGS").append("/VERSION:" + major + "." + minor);
+ }
+
+ QString msvcdsp_project;
+ if(!project->isEmpty("TARGET")) {
+ project->values("TARGET") = unescapeFilePaths(project->values("TARGET"));
+ msvcdsp_project = project->first("TARGET");
+ }
+
+ MakefileGenerator::init();
+
+ if(msvcdsp_project.isEmpty())
+ msvcdsp_project = Option::output.fileName();
+
+ msvcdsp_project = msvcdsp_project.right(msvcdsp_project.length() - msvcdsp_project.lastIndexOf("\\") - 1);
+ int dotFind = msvcdsp_project.lastIndexOf(".");
+ if(dotFind != -1)
+ msvcdsp_project = msvcdsp_project.left(dotFind);
+ msvcdsp_project.replace("-", "");
+
+ project->values("MSVCDSP_PROJECT").append(msvcdsp_project);
+
+ QStringList &proj = project->values("MSVCDSP_PROJECT");
+
+ for(QStringList::Iterator it = proj.begin(); it != proj.end(); ++it)
+ (*it).replace(QRegExp("\\.[a-zA-Z0-9_]*$"), "");
+
+ if(!project->values("QMAKE_APP_FLAG").isEmpty()) {
+ if(project->isActiveConfig("console")) {
+ project->values("MSVCDSP_TARGETTYPE").append("Console Application");
+ project->values("MSVCDSP_DSPTYPE").append("0x0103");
+ project->values("MSVCDSP_DEFINES").append(" /D \"_CONSOLE\" ");
+ } else {
+ project->values("MSVCDSP_TARGETTYPE").append("Application");
+ project->values("MSVCDSP_DSPTYPE").append("0x0101");
+ project->values("MSVCDSP_DEFINES").append(" /D \"_WINDOWS\" ");
+ }
+ } else {
+ if(project->isActiveConfig("dll")) {
+ project->values("MSVCDSP_TARGETTYPE").append("Dynamic-Link Library");
+ project->values("MSVCDSP_DSPTYPE").append("0x0102");
+ project->values("MSVCDSP_DEFINES").append(" /D \"_USRDLL\" ");
+ } else {
+ project->values("MSVCDSP_TARGETTYPE").append("Static Library");
+ project->values("MSVCDSP_DSPTYPE").append("0x0104");
+ project->values("MSVCDSP_DEFINES").append(" /D \"_LIB\" ");
+ }
+ }
+
+ project->values("MSVCDSP_LFLAGS") += project->values("QMAKE_LFLAGS");
+
+ if(!project->values("QMAKE_LIBDIR").isEmpty())
+ project->values("MSVCDSP_LFLAGS").append(valGlue(
+ escapeFilePaths(project->values("QMAKE_LIBDIR")),
+ "/LIBPATH:"," /LIBPATH:",""));
+
+ project->values("MSVCDSP_DEFINES").append(varGlue("DEFINES","/D ","" " /D ",""));
+ project->values("MSVCDSP_DEFINES").append(varGlue("PRL_EXPORT_DEFINES","/D ","" " /D ",""));
+ project->values("MSVCDSP_DEFINES").append(" /D \"WIN32\" ");
+
+ QStringList &libs = project->values("QMAKE_LIBS");
+ for(QStringList::Iterator libit = libs.begin(); libit != libs.end(); ++libit) {
+ project->values("MSVCDSP_LIBS").append(" " + escapeFilePath(*libit));
+ }
+
+ QStringList &incs = project->values("INCLUDEPATH");
+ for(QStringList::Iterator incit = incs.begin(); incit != incs.end(); ++incit) {
+ QString inc = (*incit);
+ project->values("MSVCDSP_INCPATH").append("/I" + escapeFilePath(inc));
+ }
+ project->values("MSVCDSP_INCPATH").append("/I" + escapeFilePath(specdir()));
+
+ QString dest;
+ QString preLinkStep;
+ QString postLinkStep;
+ QString copyDllStep;
+
+ if(!project->values("QMAKE_PRE_LINK").isEmpty())
+ preLinkStep += var("QMAKE_PRE_LINK");
+
+ if(!project->values("QMAKE_POST_LINK").isEmpty())
+ postLinkStep += var("QMAKE_POST_LINK");
+
+ // don't destroy the target, it is used by prl writer.
+ if(!project->values("DESTDIR").isEmpty()) {
+ dest = project->first("DESTDIR");
+ project->values("DESTDIR").first() = dest;
+ dest = project->values("TARGET").first() + project->first("TARGET_EXT");
+ dest.prepend(project->first("DESTDIR"));
+ Option::fixPathToTargetOS(dest);
+ dest = escapeFilePath(dest);
+
+ project->values("MSVCDSP_TARGET").append(
+ QString("/out:") + dest);
+ if(project->isActiveConfig("dll")) {
+ QString imp = dest;
+ imp.replace(".dll", ".lib");
+ project->values("MSVCDSP_TARGET").append(QString(" /implib:") + escapeFilePath(imp));
+ }
+ }
+
+ if(project->isActiveConfig("dll") && !project->values("DLLDESTDIR").isEmpty()) {
+ QStringList dlldirs = project->values("DLLDESTDIR");
+ if(dlldirs.count())
+ copyDllStep += "\t";
+ for(QStringList::Iterator dlldir = dlldirs.begin(); dlldir != dlldirs.end(); ++dlldir) {
+ copyDllStep += "copy \"$(TargetPath)\" " + escapeFilePath(Option::fixPathToTargetOS(*dlldir)) + "\t";
+ }
+ }
+
+ if(!preLinkStep.isEmpty()) {
+ project->values("MSVCDSP_PRE_LINK").append(
+ "# Begin Special Build Tool\n"
+ "SOURCE=$(InputPath)\n"
+ "PreLink_Desc=Post Build Step\n"
+ "PreLink_Cmds=" + preLinkStep + "\n"
+ "# End Special Build Tool\n");
+ }
+
+ if(!postLinkStep.isEmpty() || !copyDllStep.isEmpty()) {
+ project->values("MSVCDSP_POST_LINK").append(
+ "# Begin Special Build Tool\n"
+ "SOURCE=$(InputPath)\n"
+ "PostBuild_Desc=Post Build Step\n"
+ "PostBuild_Cmds=" + postLinkStep + copyDllStep + "\n"
+ "# End Special Build Tool\n");
+ }
+
+ QStringList &formList = project->values("FORMS");
+ for(QStringList::ConstIterator hit = formList.begin(); hit != formList.end(); ++hit) {
+ if(exists(*hit + ".h"))
+ project->values("SOURCES").append(*hit + ".h");
+ }
+ QStringList &form3List = project->values("FORMS3");
+ for(QStringList::ConstIterator hit = form3List.begin(); hit != form3List.end(); ++hit) {
+ if(exists(*hit + ".h"))
+ project->values("SOURCES").append(*hit + ".h");
+ }
+
+ project->values("QMAKE_INTERNAL_PRL_LIBS") << "MSVCDSP_LIBS";
+
+ // Move some files around //### is this compat?
+ if (!project->values("IMAGES").isEmpty()) {
+ QString imageFactory(project->first("QMAKE_IMAGE_COLLECTION"));
+ project->values("GENERATED_SOURCES") += imageFactory;
+ project->values("SOURCES").removeAll(imageFactory);
+ }
+
+ // Setup PCH variables
+ precompH = project->first("PRECOMPILED_HEADER");
+ namePCH = fileInfo(precompH).fileName();
+ 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 PRECOMPILED_HEADER to HEADERS
+ if (!project->values("HEADERS").contains(precompH))
+ project->values("HEADERS") += precompH;
+ // Add precompile compiler options
+ project->values("PRECOMPILED_FLAGS") = QStringList("/Fp" + precompPch + " /Yu" + escapeFilePath(namePCH) + " /FI" + escapeFilePath(namePCH) + " ");
+ // Return to variable pool
+ project->values("PRECOMPILED_OBJECT") = QStringList(precompObj);
+ project->values("PRECOMPILED_PCH") = QStringList(precompPch);
+ }
+
+ QString buildName;
+ if (!var("BUILD_NAME").isEmpty())
+ buildName = var("BUILD_NAME");
+ else if (project->isActiveConfig("debug"))
+ buildName = "Debug";
+ else
+ buildName = "Release";
+
+ project->values("MSVCDSP_CONFIG_NAME") = QStringList(" - " + platform + " " + buildName);
+}
+
+void DspMakefileGenerator::processPrlVariable(const QString &var, const QStringList &l)
+{
+ if(var == "QMAKE_PRL_DEFINES") {
+ QStringList &out = project->values("MSVCDSP_DEFINES");
+ for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
+ if(out.indexOf((*it)) == -1)
+ out.append((" /D \"" + *it + "\""));
+ }
+ } else {
+ MakefileGenerator::processPrlVariable(var, l);
+ }
+}
+
+bool DspMakefileGenerator::openOutput(QFile &file, const QString &build) const
+{
+ QString outdir;
+ if(!file.fileName().isEmpty()) {
+ if(QDir::isRelativePath(file.fileName()))
+ file.setFileName(Option::output_dir + "/" + file.fileName()); //pwd when qmake was run
+ QFileInfo fi(fileInfo(file.fileName()));
+ if(fi.isDir())
+ outdir = file.fileName() + QDir::separator();
+ }
+
+ if(!outdir.isEmpty() || file.fileName().isEmpty()) {
+ QString ext = project->first("DSP_EXTENSION");
+ if(project->first("TEMPLATE") == "vcsubdirs") {
+ if (!project->first("DSW_EXTENSION").isEmpty())
+ ext = project->first("DSW_EXTENSION");
+ else
+ ext = ".dsw";
+ }
+ QString outputName = unescapeFilePath(project->first("QMAKE_DSP_PROJECT_NAME"));
+ if (!project->first("MAKEFILE").isEmpty())
+ outputName = unescapeFilePath(project->first("MAKEFILE"));
+ if (outputName.isEmpty())
+ outputName = unescapeFilePath(project->first("QMAKE_ORIG_TARGET"));
+ file.setFileName(outdir + outputName + ext);
+ }
+
+ if(QDir::isRelativePath(file.fileName())) {
+ QString ofile = Option::fixPathToLocalOS(file.fileName());
+ int slashfind = ofile.lastIndexOf(Option::dir_sep);
+ if(slashfind == -1) {
+ ofile = ofile.replace(QRegExp("-"), "_");
+ } else {
+ int hypenfind = ofile.indexOf('-', slashfind);
+ while (hypenfind != -1 && slashfind < hypenfind) {
+ ofile = ofile.replace(hypenfind, 1, "_");
+ hypenfind = ofile.indexOf('-', hypenfind + 1);
+ }
+ }
+ file.setFileName(Option::fixPathToLocalOS(qmake_getpwd() + Option::dir_sep + ofile));
+ }
+ return Win32MakefileGenerator::openOutput(file, build);
+}
+
+bool DspMakefileGenerator::mergeBuildProject(MakefileGenerator *other)
+{
+
+ mergedProjects.prepend(static_cast<DspMakefileGenerator*>(other));
+ return true;
+}
+
+bool DspMakefileGenerator::writeProjectMakefile()
+{
+ bool ret = true;
+
+ 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 DSP: no single configuration created, cannot output project!");
+ return false;
+ }
+ debug_msg(1, "Generator: MSVC 6: Writing project file");
+
+ writeDspHeader(t);
+ for (int i = 0; i < mergedProjects.count(); ++i) {
+ DspMakefileGenerator* config = mergedProjects.at(i);
+ t << endl;
+ if (i == 0)
+ t << "!IF";
+ else
+ t << "!ELSEIF";
+ t << " \"$(CFG)\" == \"" << configName(config) << "\"" << endl;
+ t << endl;
+ writeDspConfig(t, config);
+ }
+ t << endl;
+ t << "!ENDIF " << endl;
+ t << endl;
+ t << "# Begin Target" << endl;
+ t << endl;
+ for (int i = 0; i < mergedProjects.count(); ++i)
+ t << "# Name \"" << configName(mergedProjects.at(i)) << "\"" << endl;
+ t << endl;
+
+ QMap< QString, QSet<QString> > files;
+
+ // merge source files
+ for (int i = 0; i < mergedProjects.count(); ++i) {
+
+ DspMakefileGenerator* config = mergedProjects.at(i);
+
+ files["DEF_FILE"] += config->project->values("DEF_FILE").toSet();
+ files["SOURCES"] += config->project->values("SOURCES").toSet();
+ files["HEADERS"] += config->project->values("HEADERS").toSet();
+ files["INTERFACES"] += config->project->values("INTERFACES").toSet();
+ files["FORMS"] += config->project->values("FORMS").toSet();
+ files["FORMS"] += config->project->values("FORMS3").toSet();
+ files["IMAGES"] += config->project->values("IMAGES").toSet();
+ files["RC_FILE"] += config->project->values("RC_FILE").toSet();
+ files["RESOURCES"] += config->project->values("RESOURCES").toSet();
+ files["TRANSLATIONS"] += config->project->values("TRANSLATIONS").toSet();
+ files["LEXSOURCES"] += config->project->values("LEXSOURCES").toSet();
+ files["YACCSOURCES"] += config->project->values("YACCSOURCES").toSet();
+ files["TYPELIBS"] += config->project->values("TYPELIBS").toSet();
+
+ if (!config->project->isEmpty("QMAKE_EXTRA_COMPILERS")) {
+ const QStringList &quc = config->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) {
+ if (*input != "UIC3_HEADERS")
+ files[(*input)] += config->project->values((*input)).toSet();
+ }
+ }
+ }
+ }
+
+ QStringList keys = files.keys();
+ for (int k = 0; k < keys.size(); ++k)
+ project->values(keys.at(k)) = QList<QString>::fromSet(files[keys.at(k)]);
+
+ QStringList listNames = QString("SOURCES|DEF_FILE").split("|");
+ QStringList allListNames = listNames;
+ writeFileGroup(t, listNames, "Source Files", "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat");
+ listNames = QStringList("HEADERS");
+ allListNames += listNames;
+ writeFileGroup(t, listNames, "Header Files", "h;hpp;hxx;hm;inl");
+ listNames = QString("FORMS|INTERFACES|FORMS3").split("|");
+ allListNames += listNames;
+ writeFileGroup(t, listNames, "Form Files", "ui");
+ listNames = QStringList("IMAGES");
+ allListNames += listNames;
+ writeFileGroup(t, listNames, "Image Files", "");
+ listNames = QString("RC_FILE|RESOURCES").split("|");
+ allListNames += listNames;
+ writeFileGroup(t, listNames, "Resources", "rc;qrc");
+ listNames = QStringList("TRANSLATIONS");
+ allListNames += listNames;
+ writeFileGroup(t, listNames, "Translations", "ts;xlf");
+ listNames = QStringList("LEXSOURCES");
+ allListNames += listNames;
+ writeFileGroup(t, listNames, "Lexables", "l");
+ listNames = QStringList("YACCSOURCES");
+ allListNames += listNames;
+ writeFileGroup(t, listNames, "Yaccables", "y");
+ listNames = QStringList("TYPELIBS");
+ allListNames += listNames;
+ writeFileGroup(t, listNames, "Type Libraries", "tlb;olb");
+
+ for (int l = 0; l < allListNames.size(); ++l)
+ keys.removeAll(allListNames.at(l));
+
+ for (int k = 0; k < keys.size(); ++k)
+ writeFileGroup(t, QStringList(keys.at(k)), keys.at(k) + " Files", "");
+
+ // done last as generated may have changed when creating build rules for the above
+ for (int i = 0; i < mergedProjects.count(); ++i) {
+
+ DspMakefileGenerator* config = mergedProjects.at(i);
+
+ config->project->values("SWAPPED_BUILD_STEPS") = config->swappedBuildSteps.keys();
+ files["SWAPPED_BUILD_STEPS"] += config->project->values("SWAPPED_BUILD_STEPS").toSet();
+
+ files["GENERATED_SOURCES"] += config->project->values("GENERATED_SOURCES").toSet();
+ files["GENERATED_FILES"] += config->project->values("GENERATED_FILES").toSet();
+ }
+
+ project->values("SWAPPED_BUILD_STEPS") = QList<QString>::fromSet(files["SWAPPED_BUILD_STEPS"]);
+ project->values("GENERATED_SOURCES") = QList<QString>::fromSet(files["GENERATED_SOURCES"]);
+ project->values("GENERATED_FILES") = QList<QString>::fromSet(files["GENERATED_FILES"]);
+
+ writeFileGroup(t, QString("GENERATED_SOURCES|GENERATED_FILES|SWAPPED_BUILD_STEPS").split("|"), "Generated", "");
+ t << endl;
+ t << "# End Target" << endl;
+ t << "# End Project" << endl;
+ }else if(project->first("TEMPLATE") == "vcsubdirs") {
+ ret = writeMakefile(t);
+ }
+
+ return ret;
+}
+
+const char _dswHeader60[] = "Microsoft Developer Studio Workspace File, Format Version 6.00\n";
+const char _dswWarning[] = "# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\n";
+const char _dswDevider[] = "###############################################################################\n";
+const char _dswProjectName[] = "Project: \"%1\"=%2 - Package Owner=<4>\n"; // %1 = project name, %2 = project path
+const char _dswPackage5Start[] = "Package=<5>\n{{{\n";
+const char _dswPackage5Stop[] = "}}}\n";
+const char _dswPackage4Start[] = "Package=<4>\n{{{\n";
+const char _dswPackage4Stop[] = "}}}\n";
+const char _dswProjectDep[] = " Begin Project Dependency\n Project_Dep_Name %1\n End Project Dependency\n"; // %1 = project name
+const char _dswGlobal[] = "Global:\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<3>\n{{{\n}}}\n\n";
+
+
+struct WorkspaceDepend {
+ QString dspProjectFile, orig_target, target;
+ QStringList dependencies;
+};
+
+void DspMakefileGenerator::writeSubDirs(QTextStream &t)
+{
+ // Output headers
+ t << _dswHeader60;
+ t << _dswWarning;
+ t << endl;
+
+ QHash<QString, WorkspaceDepend*> workspace_depends;
+ QList<WorkspaceDepend*> workspace_cleanup;
+ QStringList subdirs = project->values("SUBDIRS");
+ 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");
+
+ for(int i = 0; i < subdirs.size(); ++i) {
+ QString tmp = subdirs.at(i);
+ if(!project->isEmpty(tmp + ".file")) {
+ if(!project->isEmpty(tmp + ".subdir"))
+ warn_msg(WarnLogic, "Cannot assign both file and subdir for subdir %s",
+ tmp.toLatin1().constData());
+ tmp = project->first(tmp + ".file");
+ } else if(!project->isEmpty(tmp + ".subdir")) {
+ tmp = project->first(tmp + ".subdir");
+ }
+
+ 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() + ".pro";
+ 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 Workspace 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") {
+ QStringList tmp_proj_subdirs = tmp_proj.variables()["SUBDIRS"];
+ for(int x = 0; x < tmp_proj_subdirs.size(); ++x) {
+ QString tmpdir = tmp_proj_subdirs.at(x);
+ if(!tmp_proj.isEmpty(tmpdir + ".file")) {
+ if(!tmp_proj.isEmpty(tmpdir + ".subdir"))
+ warn_msg(WarnLogic, "Cannot assign both file and subdir for subdir %s",
+ tmpdir.toLatin1().constData());
+ tmpdir = tmp_proj.first(tmpdir + ".file");
+ } else if(!tmp_proj.isEmpty(tmpdir + ".subdir")) {
+ tmpdir = tmp_proj.first(tmpdir + ".subdir");
+ }
+ 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
+ DspMakefileGenerator tmp_dsp;
+ tmp_dsp.setNoIO(true);
+ tmp_dsp.setProjectFile(&tmp_proj);
+ if(Option::debug_level) {
+ 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_ORIG_TARGET].vcproj
+ QString dsp = unescapeFilePath(tmp_dsp.project->first("MSVCDSP_PROJECT") + project->first("DSP_EXTENSION"));
+
+ // If file doesn't exsist, then maybe the users configuration
+ // doesn't allow it to be created. Skip to next...
+ if(!exists(qmake_getpwd() + Option::dir_sep + dsp)) {
+ warn_msg(WarnLogic, "Ignored (not found) '%s'", QString(qmake_getpwd() + Option::dir_sep + dsp).toLatin1().constData());
+ goto nextfile; // # Dirty!
+ }
+
+ WorkspaceDepend *newDep = new WorkspaceDepend;
+ newDep->dspProjectFile = fileFixify(dsp);
+ newDep->orig_target = unescapeFilePath(tmp_proj.first("QMAKE_ORIG_TARGET"));
+ newDep->target = tmp_proj.first("MSVCDSP_PROJECT").section(Option::dir_sep, -1) + tmp_proj.first("TARGET_EXT");
+
+ // 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 projects having mocable sourcefiles are dependent on moc.exe
+ if(tmp_proj.variables()["CONFIG"].contains("moc"))
+ newDep->dependencies << "moc.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()) {
+ QString dep = tmp_proj.first((*it) + ".commands").section('/', -1).section('\\', -1);
+ if (!newDep->dependencies.contains(dep))
+ newDep->dependencies << dep;
+ }
+ }
+ }
+
+ // Add all unknown libs to the deps
+ QStringList where("QMAKE_LIBS");
+ 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).trimmed();
+ 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);
+ }
+ }
+ }
+ workspace_cleanup.append(newDep);
+ workspace_depends.insert(newDep->target, newDep);
+
+ debug_msg(1, "Generator: MSVC: Added project (name:'%s' path:'%s' deps:'%s')",
+ qPrintable(newDep->target) , qPrintable(newDep->dspProjectFile),
+ qPrintable(newDep->dependencies.join(";")));
+ }
+ }
+nextfile:
+ qmake_setpwd(oldpwd);
+ }
+ }
+ }
+
+ // Restore previous after_user_var options
+ Option::after_user_vars = old_after_vars;
+
+ // Output all projects
+ QString dswProjectName = QLatin1String(_dswProjectName);
+ QString dswProjectDep = QLatin1String(_dswProjectDep);
+ for(QList<WorkspaceDepend*>::Iterator it = workspace_cleanup.begin(); it != workspace_cleanup.end(); ++it) {
+ t << _dswDevider;
+ t << endl;
+ t << dswProjectName.arg((*it)->orig_target).arg((*it)->dspProjectFile);
+ t << endl;
+ t << _dswPackage5Start;
+ t << _dswPackage5Stop;
+ t << endl;
+ t << _dswPackage4Start;
+
+ // Output project dependencies
+ for(QStringList::iterator dit = (*it)->dependencies.begin(); dit != (*it)->dependencies.end(); ++dit) {
+ if(WorkspaceDepend *vc = workspace_depends[*dit])
+ t << dswProjectDep.arg(vc->orig_target);
+ }
+
+ t << _dswPackage4Stop;
+ }
+
+ // Output global part
+ t << _dswDevider << endl;
+ t << _dswGlobal;
+ t << _dswDevider;
+ t << endl << endl;
+}
+
+class FolderGroup
+{
+public:
+ QString name;
+ QString filter;
+ QMap<QString, FolderGroup *> subFolders;
+ QMap<QString, QString> files;
+
+ void insertStructured(const QString &file, const QString &fileListName)
+ {
+ QStringList path = QFileInfo(file).path().split("/");
+ if (!path.isEmpty() && path.at(0) == ".")
+ path.takeAt(0);
+ FolderGroup *currentFolder = this;
+ for (int i = 0; i < path.size(); i++) {
+ if (currentFolder->subFolders.contains(path.at(i))) {
+ currentFolder = currentFolder->subFolders.value(path.at(i));
+ } else {
+ FolderGroup *newFolder = new FolderGroup;
+ newFolder->name = path.at(i);
+ currentFolder->subFolders.insert(path.at(i), newFolder);
+ currentFolder = newFolder;
+ }
+ }
+ currentFolder->files.insert(file, fileListName);
+ }
+
+ void insertFlat(const QString &file, const QString &fileListName)
+ {
+ files.insert(file, fileListName);
+ }
+
+ ~FolderGroup()
+ {
+ qDeleteAll(subFolders.values());
+ }
+};
+
+bool DspMakefileGenerator::writeFileGroup(QTextStream &t, const QStringList &listNames, const QString &group, const QString &filter)
+{
+ FolderGroup root;
+ root.name = group;
+ root.filter = filter;
+
+ for (int i = 0; i < listNames.count(); ++i) {
+ QStringList list = project->values(listNames.at(i));
+ for (int j = 0; j < list.count(); ++j) {
+ const QString name = list.at(j);
+ if (name.isEmpty())
+ continue;
+ if (project->isActiveConfig("flat"))
+ root.insertFlat(name, listNames.at(i));
+ else
+ root.insertStructured(name, listNames.at(i));
+ }
+ }
+
+ if (root.files.isEmpty() && root.subFolders.isEmpty())
+ return true;
+
+ writeSubFileGroup(t, &root);
+
+ return true;
+}
+
+void DspMakefileGenerator::writeSubFileGroup(QTextStream &t, FolderGroup *folder)
+{
+ t << "# Begin Group \"" << folder->name << "\"" << endl;
+ t << "# PROP Default_Filter \"" << folder->filter << "\"" << endl;
+ QMap<QString, FolderGroup *>::const_iterator folderIt = folder->subFolders.begin();
+ while (folderIt != folder->subFolders.end()) {
+ writeSubFileGroup(t, folderIt.value());
+ ++folderIt;
+ }
+ QMap<QString, QString>::const_iterator it = folder->files.begin();
+ while (it != folder->files.end()) {
+ t << "# Begin Source File" << endl;
+ t << "SOURCE=" << escapeFilePath(it.key()) << endl;
+ writeBuildstepForFile(t, it.key(), it.value());
+ t << "# End Source File" << endl;
+ t << endl;
+ ++it;
+ }
+ t << "# End Group" << endl;
+ t << endl;
+}
+
+bool DspMakefileGenerator::writeBuildstepForFile(QTextStream &t, const QString &file, const QString &listName)
+{
+
+ if (!mergedProjects.count()) {
+ t << writeBuildstepForFileForConfig(file, listName, this);
+ return true;
+ }
+
+ //only add special build rules when needed
+
+ QStringList specialBuilds;
+ int i = 0;
+ for (i = 0; i < mergedProjects.count(); ++i)
+ specialBuilds += writeBuildstepForFileForConfig(file, listName, mergedProjects.at(i));
+
+ // no special build just return
+ if (specialBuilds.join("").isEmpty())
+ return true;
+
+ for (i = 0; i < mergedProjects.count(); ++i) {
+ if (i == 0)
+ t << "!IF";
+ else
+ t << "!ELSEIF";
+ t << " \"$(CFG)\" == \"" << configName(mergedProjects.at(i)) << "\"" << endl;
+ t << endl;
+ t << specialBuilds.at(i);
+ t << endl;
+ }
+
+ t << "!ENDIF" << endl;
+
+ return true;
+}
+
+bool DspMakefileGenerator::writeDspConfig(QTextStream &t, DspMakefileGenerator *config)
+{
+
+ bool isDebug = config->project->isActiveConfig("debug");
+ bool staticLibTarget = config->var("MSVCDSP_DSPTYPE") == "0x0104";
+
+ QString outDir = Option::fixPathToTargetOS(config->project->first("DESTDIR"));
+ while (outDir.endsWith(Option::dir_sep))
+ outDir.chop(1);
+ outDir = config->escapeFilePath(outDir);
+
+ QString intDir = config->project->first("OBJECTS_DIR");
+ while (intDir.endsWith(Option::dir_sep))
+ intDir.chop(1);
+ intDir = config->escapeFilePath(intDir);
+
+ t << "# PROP BASE Use_MFC 0" << endl;
+ t << "# PROP BASE Use_Debug_Libraries " << (isDebug ? "1" : "0") << endl;
+ t << "# PROP BASE Output_Dir " << outDir << endl;
+ t << "# PROP BASE Intermediate_Dir " << intDir << endl;
+ t << "# PROP BASE Target_Dir \"\"" << endl;
+ t << "# PROP Use_MFC 0" << endl;
+ t << "# PROP Use_Debug_Libraries " << (isDebug ? "1" : "0") << endl;
+
+ t << "# PROP Output_Dir " << outDir << endl;
+ t << "# PROP Intermediate_Dir " << intDir << endl;
+ if (config->project->isActiveConfig("dll") || config->project->isActiveConfig("plugin"))
+ t << "# PROP Ignore_Export_Lib 1" << endl;
+ t << "# PROP Target_Dir \"\"" << endl;
+ t << "# ADD CPP " << config->var("MSVCDSP_INCPATH") << " /c /FD " << config->var("QMAKE_CXXFLAGS") << " " << config->var("MSVCDSP_DEFINES") << " " << config->var("PRECOMPILED_FLAGS") << endl;
+ t << "# ADD MTL /nologo /mktyplib203 /win32 /D " << (isDebug ? "\"_DEBUG\"" : "\"NDEBUG\"") << endl;
+ t << "# ADD RSC /l 0x409 /d " << (isDebug ? "\"_DEBUG\"" : "\"NDEBUG\"") << endl;
+ t << "# ADD BSC32 /nologo" << endl;
+ if (staticLibTarget) {
+ t << "LIB32=" << config->var("QMAKE_LIB") << endl;
+ t << "# ADD LIB32 " << config->var("MSVCDSP_TARGET") << " " << config->var("PRECOMPILED_OBJECT") << endl;
+ } else {
+ t << "LINK32=" << config->var("QMAKE_LINK") << endl;
+ t << "# ADD LINK32 " << config->var("MSVCDSP_LFLAGS") << " " << config->var("MSVCDSP_LIBS") << " " << config->var("MSVCDSP_TARGET") << " " << config->var("PRECOMPILED_OBJECT") << endl;
+ }
+
+ if (!config->project->values("MSVCDSP_PRE_LINK").isEmpty())
+ t << config->project->values("MSVCDSP_PRE_LINK").first();
+
+ if (!config->project->values("MSVCDSP_POST_LINK").isEmpty())
+ t << config->project->values("MSVCDSP_POST_LINK").first();
+
+ return true;
+}
+
+QString DspMakefileGenerator::writeBuildstepForFileForConfig(const QString &file, const QString &listName, DspMakefileGenerator *config)
+{
+ QString ret;
+ QTextStream t(&ret);
+
+ // exclude from build
+ if (!config->project->values(listName).contains(file)) {
+ t << "# PROP Exclude_From_Build 1" << endl;
+ return ret;
+ }
+
+ if (config->usePCH) {
+ bool c_file = false;
+ for (QStringList::Iterator it = Option::c_ext.begin(); it != Option::c_ext.end(); ++it) {
+ if (file.endsWith(*it)) {
+ c_file = true;
+ break;
+ }
+ }
+ if(c_file) {
+ t << "# SUBTRACT CPP /FI" << config->escapeFilePath(config->namePCH) << " /Yu" << config->escapeFilePath(config->namePCH) << " /Fp" << endl;
+ return ret;
+ } else if (config->precompH.endsWith(file)) {
+ // ### dependency list quickly becomes too long for VS to grok...
+ t << "USERDEP_" << file << "=" << config->valGlue(config->escapeFilePaths(config->findDependencies(config->precompH)), "", "\t", "") << endl;
+ t << endl;
+ t << "# Begin Custom Build - Creating precompiled header from " << file << "..." << endl;
+ t << "InputPath=.\\" << config->escapeFilePath(file) << endl << endl;
+ t << config->precompPch + ": $(SOURCE) \"$(IntDir)\" \"$(OUTDIR)\"" << endl;
+ t << "\t" << config->var("QMAKE_CC") << " /TP /W3 /FD /c /Yc /Fp" << config->precompPch << " /Fo" << config->precompObj << " /Fd\"$(IntDir)\\\\\" " << file << " ";
+ t << config->var("MSVCDSP_INCPATH") << " " << config->var("MSVCDSP_DEFINES") << " " << config->var("QMAKE_CXXFLAGS") << endl;
+ t << "# End Custom Build" << endl << endl;
+ return ret;
+ }
+ }
+
+ QString fileBase = QFileInfo(file).completeBaseName();
+
+ bool hasBuiltin = config->hasBuiltinCompiler(file);
+ BuildStep allSteps;
+
+ if (!config->swappedBuildSteps.contains(file)) {
+ QStringList compilers = config->project->values("QMAKE_EXTRA_COMPILERS");
+ for (int i = 0; i < compilers.count(); ++i) {
+ QString compiler = compilers.at(i);
+ if (config->project->values(compiler + ".input").isEmpty())
+ continue;
+ QString input = config->project->values(compiler + ".input").first();
+ QStringList inputList = config->project->values(input);
+ if (!inputList.contains(file))
+ continue;
+
+ QStringList compilerCommands = config->project->values(compiler + ".commands");
+ QStringList compilerOutput = config->project->values(compiler + ".output");
+ if (compilerCommands.isEmpty() || compilerOutput.isEmpty())
+ continue;
+
+ QStringList compilerName = config->project->values(compiler + ".name");
+ if (compilerName.isEmpty())
+ compilerName << compiler;
+ QStringList compilerDepends = config->project->values(compiler + ".depends");
+ QString compilerDependsCommand = config->project->values(compiler + ".depend_command").join(" ");
+ if (!compilerDependsCommand.isEmpty()) {
+ if(!config->canExecute(compilerDependsCommand))
+ compilerDependsCommand = QString();
+ }
+ QStringList compilerConfig = config->project->values(compiler + ".CONFIG");
+
+ if (!config->verifyExtraCompiler(compiler, file))
+ continue;
+
+ bool combineAll = compilerConfig.contains("combine");
+ if (combineAll && inputList.first() != file)
+ continue;
+
+ QString fileIn("$(InputPath)");
+
+ if (combineAll && !inputList.isEmpty()) {
+ fileIn = inputList.join(" ");
+ compilerDepends += inputList;
+ }
+
+ QString fileOut = compilerOutput.first();
+ QString fileOutBase = QFileInfo(fileOut).completeBaseName();
+ fileOut.replace("${QMAKE_FILE_IN}", fileIn);
+ fileOut.replace("${QMAKE_FILE_BASE}", fileBase);
+ fileOut.replace("${QMAKE_FILE_OUT_BASE}", fileOutBase);
+ fileOut.replace('/', '\\');
+
+ BuildStep step;
+ for (int i2 = 0; i2 < compilerDepends.count(); ++i2) {
+ QString dependency = compilerDepends.at(i2);
+ dependency.replace("${QMAKE_FILE_IN}", fileIn);
+ dependency.replace("${QMAKE_FILE_BASE}", fileBase);
+ dependency.replace("${QMAKE_FILE_OUT_BASE}", fileOutBase);
+ dependency.replace('/', '\\');
+ if (!step.deps.contains(dependency, Qt::CaseInsensitive))
+ step.deps << dependency;
+ }
+ // depends command
+ if (!compilerDependsCommand.isEmpty() && config->doDepends()) {
+ char buff[256];
+ QString dep_cmd = config->replaceExtraCompilerVariables(compilerDependsCommand, file,
+ fileOut);
+ dep_cmd = Option::fixPathToLocalOS(dep_cmd, true, false);
+ if(config->canExecute(dep_cmd)) {
+ 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())
+ step.deps += config->fileFixify(indeps.replace('\n', ' ').simplified().split(' '));
+ }
+ }
+ }
+
+
+ QString mappedFile;
+ if (hasBuiltin) {
+ mappedFile = fileOut;
+ fileOut = fileIn;
+ fileIn = file;
+ }
+
+ step.buildStep += " \\\n\t";
+ QString command(compilerCommands.join(" "));
+ // Replace any newlines with proper line-continuance
+ command.replace("\n", " \\\n\t");
+ // Might be a macro, and not a valid filename, so the replaceExtraCompilerVariables() would eat it
+ command.replace("${QMAKE_FILE_IN}", config->escapeFilePath(fileIn));
+ command.replace("${QMAKE_FILE_BASE}", config->escapeFilePath(fileBase));
+ command.replace("${QMAKE_FILE_OUT_BASE}", config->escapeFilePath(fileOutBase));
+ command.replace("${QMAKE_FILE_OUT}", config->escapeFilePath(fileOut));
+
+ command = config->replaceExtraCompilerVariables(command, fileIn, fileOut);
+
+ step.buildName = compilerName.first();
+ step.buildStep += command;
+ step.buildOutputs += fileOut;
+
+ if (hasBuiltin) {
+ step.deps << fileIn;
+ config->swappedBuildSteps[mappedFile] = step;
+ } else {
+ allSteps << step;
+ }
+ }
+ } else {
+ allSteps << config->swappedBuildSteps.value(file);
+ }
+
+ if (allSteps.buildStep.isEmpty())
+ return ret;
+
+ int i;
+ QStringList dependencyList;
+ // remove dependencies that are also output
+ for (i = 0; i < 1; ++i) {
+ QStringList buildOutput(allSteps.buildOutputs.at(i));
+
+ for (int i2 = 0; i2 < allSteps.deps.count(); ++i2) {
+ QString dependency = allSteps.deps.at(i2);
+ if (!buildOutput.contains(dependency) && !dependencyList.contains(dependency))
+ dependencyList << dependency;
+ }
+ }
+ QString allDependencies = config->valGlue(dependencyList, "", "\t", "");
+ t << "USERDEP_" << file << "=" << allDependencies << endl;
+ t << "# PROP Ignore_Default_Tool 1" << endl;
+ t << "# Begin Custom Build - Running " << allSteps.buildName << " on " << file << endl;
+ t << "InputPath=" << file << endl;
+ t << "BuildCmds= " << allSteps.buildStep << endl;
+ for (i = 0; i < allSteps.buildOutputs.count(); ++i) {
+ t << config->escapeFilePath(allSteps.buildOutputs.at(i))
+ << " : $(SOURCE) $(INTDIR) $(OUTDIR)\n\t$(BuildCmds)\n";
+ }
+ t << endl;
+ t << "# End Custom Build" << endl;
+
+ return ret;
+}
+
+QT_END_NAMESPACE
diff --git a/qmake/generators/win32/msvc_dsp.h b/qmake/generators/win32/msvc_dsp.h
new file mode 100644
index 0000000..a870976
--- /dev/null
+++ b/qmake/generators/win32/msvc_dsp.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MSVC_DSP_H
+#define MSVC_DSP_H
+
+#include "winmakefile.h"
+
+QT_BEGIN_NAMESPACE
+
+class FolderGroup;
+
+class DspMakefileGenerator : public Win32MakefileGenerator
+{
+ bool init_flag;
+ bool writeDspHeader(QTextStream &);
+ bool writeDspParts(QTextStream &);
+ bool writeFileGroup(QTextStream &t, const QStringList &listNames, const QString &group, const QString &filter);
+ void writeSubFileGroup(QTextStream &t, FolderGroup *folder);
+ bool writeBuildstepForFile(QTextStream &t, const QString &file, const QString &listName);
+ static bool writeDspConfig(QTextStream &t, DspMakefileGenerator *config);
+ static QString writeBuildstepForFileForConfig(const QString &file, const QString &listName, DspMakefileGenerator *config);
+ QString configName(DspMakefileGenerator * config);
+
+ bool writeMakefile(QTextStream &);
+ bool writeProjectMakefile();
+ void writeSubDirs(QTextStream &t);
+ void init();
+
+public:
+ DspMakefileGenerator();
+ ~DspMakefileGenerator();
+
+ bool openOutput(QFile &file, const QString &build) const;
+ bool hasBuiltinCompiler(const QString &filename) const;
+
+protected:
+ 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 void processPrlVariable(const QString &, const QStringList &);
+ virtual bool findLibraries();
+
+ bool usePCH;
+ QString precompH, namePCH,
+ precompObj, precompPch;
+
+ QString platform;
+
+ struct BuildStep {
+ BuildStep() {}
+ BuildStep &operator<<(const BuildStep &other) {
+ deps << other.deps;
+ buildStep += other.buildStep;
+ buildName += other.buildName;
+ buildOutputs += other.buildOutputs;
+ return *this;
+ }
+
+ QStringList deps;
+ QString buildStep;
+ QString buildName;
+ QStringList buildOutputs;
+ };
+ QMap<QString, BuildStep> swappedBuildSteps;
+
+ // Holds all configurations for glue (merged) project
+ QList<DspMakefileGenerator*> mergedProjects;
+};
+
+inline DspMakefileGenerator::~DspMakefileGenerator()
+{ }
+
+inline bool DspMakefileGenerator::findLibraries()
+{ return Win32MakefileGenerator::findLibraries("MSVCDSP_LIBS"); }
+
+QT_END_NAMESPACE
+
+#endif // MSVC_DSP_H
diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp
new file mode 100644
index 0000000..4b1b66d
--- /dev/null
+++ b/qmake/generators/win32/msvc_nmake.cpp
@@ -0,0 +1,322 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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;
+}
+
+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
+ p.remove("-Gm");
+ return p;
+ } else if (value == "QMAKE_CXXFLAGS") {
+ // Remove internal compiler error option
+ 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->values("QMAKE_QMAKE").isEmpty())
+ project->values("QMAKE_QMAKE").append("qmake");
+ 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"));
+ processVars();
+
+ if (!project->values("RES_FILE").isEmpty()) {
+ project->values("QMAKE_LIBS") += escapeFilePaths(project->values("RES_FILE"));
+ }
+
+ if(!project->values("DEF_FILE").isEmpty())
+ project->values("QMAKE_LFLAGS").append(QString("/DEF:") + escapeFilePath(project->first("DEF_FILE")));
+
+ 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_CLEAN").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.insertMulti(".", (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.insertMulti(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.insertMulti(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")) {
+ if (useSignature)
+ t << " && " << var("QMAKE_POST_LINK");
+ else
+ 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 0000000..f4e8de6
--- /dev/null
+++ b/qmake/generators/win32/msvc_nmake.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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 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 0000000..c1f5ce1
--- /dev/null
+++ b/qmake/generators/win32/msvc_objectmodel.cpp
@@ -0,0 +1,2636 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "msvc_objectmodel.h"
+#include "msvc_vcproj.h"
+#include <qstringlist.h>
+#include <qfileinfo.h>
+
+QT_BEGIN_NAMESPACE
+
+// XML Tags ---------------------------------------------------------
+const char _Configuration[] = "Configuration";
+const char _Configurations[] = "Configurations";
+const char _File[] = "File";
+const char _FileConfiguration[] = "FileConfiguration";
+const char _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));
+}
+
+// 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),
+ GlobalOptimizations(unset),
+ IgnoreStandardIncludePath(unset),
+ ImproveFloatingPointConsistency(unset),
+ InlineFunctionExpansion(expandDefault),
+ KeepComments(unset),
+ MinimalRebuild(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(pchNone),
+ WarnAsError(unset),
+ WarningLevel(warningLevel_0),
+ WholeProgramOptimization(unset),
+ CompileForArchitecture(archUnknown),
+ InterworkCalls(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);
+}
+
+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"));
+}
+
+XmlOutput &operator<<(XmlOutput &xml, const VCCLCompilerTool &tool)
+{
+ return 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)
+ << (!tool.PrecompiledHeaderFile.isEmpty() || !tool.PrecompiledHeaderThrough.isEmpty() ? xformUsePrecompiledHeaderForNET2005(tool.UsePrecompiledHeader, tool.config->CompilerVersion) : noxml())
+ << 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);
+}
+
+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':
+ 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') {
+ QString opt(option);
+ 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;
+ }
+ 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 {
+ AssemblerOutput = asmListingAssemblyOnly;
+ }
+ break;
+ case 'a':
+ AssemblerListingLocation = option+3;
+ break;
+ case 'I':
+ ForcedIncludeFiles += 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;
+ 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;
+ }
+ 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') {
+ 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;
+ PrecompiledHeaderFile = option+3;
+ break;
+ case 'c':
+ UsePrecompiledHeader = pchCreateUsingSpecific;
+ PrecompiledHeaderFile = option+3;
+ break;
+ case 'd':
+ case 'l':
+ AdditionalOptions += option;
+ break;
+ case 'u':
+ UsePrecompiledHeader = pchUseUsingSpecific;
+ PrecompiledHeaderFile = 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':
+ DebugInformationFormat = debugEditAndContinue;
+ 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;
+ }
+ }
+ }
+ 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') {
+ found = false; break;
+ }
+ CompileAsManaged = managedAssembly;
+ 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()
+ : 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),
+ 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),
+ TurnOffAssemblyGeneration(unset),
+ TypeLibraryResourceID(0)
+{
+}
+
+XmlOutput &operator<<(XmlOutput &xml, const VCLinkerTool &tool)
+{
+ return 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);
+}
+
+// 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;
+ switch (elfHash(option)) {
+ case 0x3360dbe: // /ALIGN[:number]
+ case 0x1485c34: // /ALLOWBIND[:NO]
+ case 0x6b21972: // /DEFAULTLIB:library
+ case 0x396ea92: // /DRIVER[:UPONLY | :WDM]
+ case 0xaca9d75: // /EXETYPE[:DYNAMIC | :DEV386]
+ case 0x3ad5444: // /EXPORT:entryname[,@ordinal[,NONAME]][,DATA]
+ case 0x33aec94: // /FIXED[:NO]
+ 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 0x7988f7e: // /SECTION:name,[E][R][W][S][D][K][L][P][X][,ALIGN=#]
+ case 0x0348992: // /STUB:filename
+ case 0x0034bc4: // /VXD
+ case 0x0034c50: // /WS
+ AdditionalOptions += option;
+ break;
+ case 0x679c075: // /ASSEMBLYMODULE:filename
+ AddModuleNamesToAssembly += option+15;
+ 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 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 0x003390c: // /DLL
+ // This option is not used for vcproj files
+ break;
+ case 0x33a3979: // /ENTRY:function
+ EntryPointSymbol = option+7;
+ 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 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;
+ // so we put the others in AdditionalOptions...
+ case 0x0005b94: // X64
+ 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;
+ 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 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;
+ 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)
+{
+}
+
+XmlOutput &operator<<(XmlOutput &xml, const VCMIDLTool &tool)
+{
+ return 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);
+}
+
+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;
+ switch(elfHash(option)) {
+ 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 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 0xa766524: // /cpp_opt options
+ CPreprocessOptions += option+9;
+ 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 0x8e0b0a2: // /no_def_idir
+ IgnoreStandardIncludePath = _True;
+ break;
+ case 0x65635ef: // /nologo
+ SuppressStartupBanner = _True;
+ break;
+ case 0x3656b22: // /notlb
+ GenerateTypeLibrary = _True;
+ break;
+ case 0x000035f: // /o filename
+ RedirectOutputAndErrors = option+3;
+ 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 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 0x5b1cb97: // /app_config
+ case 0x3595cf4: // /c_ext
+ case 0x5a2fc64: // /client {none|stub}
+ case 0xa64d3dd: // /confirm
+ case 0xa765b64: // /cpp_cmd cmd_line
+ case 0x35aabb2: // /cstub filename
+ case 0x03629f4: // /lcid
+ case 0x6495cc4: // /ms_ext
+ case 0x96c7a1e: // /ms_union
+ case 0x4996fa2: // /msc_ver <nnnn>
+ case 0x64ceb12: // /newtlb
+ case 0x6555a40: // /no_cpp
+ case 0xf64d6a6: // /no_default_epv
+ case 0x6dd9384: // /no_format_opt
+ case 0x556dbee: // /no_warn
+ case 0x3655a70: // /nocpp
+ case 0x2b455a3: // /oldnames
+ case 0x662bb12: // /oldtlb
+ 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 0x69c9cf2: // /server {none|stub}
+ case 0x36aabb2: // /sstub filename
+ 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)
+{
+}
+
+XmlOutput &operator<<(XmlOutput &xml, const VCLibrarianTool &tool)
+{
+ return 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);
+}
+
+// VCCustomBuildTool ------------------------------------------------
+VCCustomBuildTool::VCCustomBuildTool()
+{
+ ToolName = "VCCustomBuildTool";
+}
+
+XmlOutput &operator<<(XmlOutput &xml, const VCCustomBuildTool &tool)
+{
+ // The code below offers two ways to split custom build step commands.
+ // Normally the $$escape_expand(\n\t) is used in a project file, which is correctly translated
+ // in all generators. However, if you use $$escape_expand(\n\r) (or \n\h) instead, the VCPROJ
+ // generator will instead of binding the commands with " && " will insert a proper newline into
+ // the VCPROJ file. We sometimes use this method of splitting commands if the custom buildstep
+ // contains a command-line which is too big to run on certain OS.
+ QString cmds;
+ int end = tool.CommandLine.count();
+ for(int i = 0; i < end; ++i) {
+ QString cmdl = tool.CommandLine.at(i);
+ if (cmdl.contains("\r\t")) {
+ if (i == end - 1)
+ cmdl = cmdl.trimmed();
+ cmdl.replace("\r\t", " && ");
+ } else if (cmdl.contains("\r\n")) {
+ ;
+ } else if (cmdl.contains("\r\\h")) {
+ // The above \r\n should work, but doesn't, so we have this hack
+ cmdl.replace("\r\\h", "\r\n");
+ } else {
+ if (i < end - 1)
+ cmdl += " && ";
+ }
+ cmds += cmdl;
+ }
+ return xml
+ << tag(_Tool)
+ << attrS(_Name, tool.ToolName)
+ << attrX(_AdditionalDependencies, tool.AdditionalDependencies, ";")
+ << attrS(_CommandLine, cmds)
+ << attrS(_Description, tool.Description)
+ << attrX(_Outputs, tool.Outputs, ";")
+ << attrS(_Path, tool.ToolPath)
+ << closetag(_Tool);
+}
+
+// VCResourceCompilerTool -------------------------------------------
+VCResourceCompilerTool::VCResourceCompilerTool()
+ : Culture(rcUseDefault),
+ IgnoreStandardIncludePath(unset),
+ ShowProgress(linkProgressNotSet)
+{
+ PreprocessorDefinitions = QStringList("NDEBUG");
+}
+
+XmlOutput &operator<<(XmlOutput &xml, const VCResourceCompilerTool &tool)
+{
+ return 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);
+}
+
+// VCDeploymentTool --------------------------------------------
+VCDeploymentTool::VCDeploymentTool()
+ : RegisterOutput(registerNo)
+{
+ DeploymentTag = "DeploymentTool";
+ RemoteDirectory = "";
+}
+
+XmlOutput &operator<<(XmlOutput &xml, const VCDeploymentTool &tool)
+{
+ if (tool.AdditionalFiles.isEmpty())
+ return xml;
+ return xml
+ << tag(tool.DeploymentTag)
+ << attrS(_RemoteDirectory, tool.RemoteDirectory)
+ << attrE(_RegisterOutput, tool.RegisterOutput)
+ << attrS(_AdditionalFiles, tool.AdditionalFiles)
+ << closetag(tool.DeploymentTag);
+}
+
+// VCEventTool -------------------------------------------------
+XmlOutput &operator<<(XmlOutput &xml, const VCEventTool &tool)
+{
+ return xml
+ << tag(_Tool)
+ << attrS(_Name, tool.ToolName)
+ << attrS(_Path, tool.ToolPath)
+ << attrS(_CommandLine, tool.CommandLine)
+ << attrS(_Description, tool.Description)
+ << attrT(_ExcludedFromBuild, tool.ExcludedFromBuild)
+ << closetag(_Tool);
+}
+
+// VCPostBuildEventTool ---------------------------------------------
+VCPostBuildEventTool::VCPostBuildEventTool()
+{
+ ToolName = "VCPostBuildEventTool";
+}
+
+// VCPreBuildEventTool ----------------------------------------------
+VCPreBuildEventTool::VCPreBuildEventTool()
+{
+ ToolName = "VCPreBuildEventTool";
+}
+
+// VCPreLinkEventTool -----------------------------------------------
+VCPreLinkEventTool::VCPreLinkEventTool()
+{
+ ToolName = "VCPreLinkEventTool";
+}
+
+// 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;
+}
+
+XmlOutput &operator<<(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)
+ << tool.compiler
+ << tool.custom;
+ if (tool.ConfigurationType == typeStaticLibrary)
+ xml << tool.librarian;
+ else
+ xml << tool.linker;
+ xml << tool.idl
+ << tool.postBuild
+ << tool.preBuild
+ << tool.preLink
+ << tool.resource
+ << tool.deployment
+ << closetag(_Configuration);
+ return xml;
+}
+// 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 = str.endsWith(".h") && (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 << "* generated when creating .vcproj 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 ? QString("$(INHERIT)") : 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)) {
+ 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);
+ }
+ }
+ }
+ }
+ }
+ 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 += cmd.trimmed().split("\n", QString::SkipEmptyParts);
+ 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;
+}
+
+void VCFilter::outputFileConfig(XmlOutput &xml, const QString &filename)
+{
+ // Clearing each filter tool
+ useCustomBuildTool = false;
+ useCompilerTool = false;
+ CustomBuildTool = VCCustomBuildTool();
+ CompilerTool = VCCLCompilerTool();
+
+ // Unset some default options
+ CompilerTool.BufferSecurityCheck = unset;
+ CompilerTool.DebugInformationFormat = debugUnknown;
+ CompilerTool.ExceptionHandling = ehDefault;
+ CompilerTool.GeneratePreprocessedFile = preprocessUnknown;
+ CompilerTool.Optimization = optimizeDefault;
+ CompilerTool.ProgramDataBaseFileName.clear();
+ CompilerTool.RuntimeLibrary = rtUnknown;
+ CompilerTool.WarningLevel = warningLevelUnknown;
+ CompilerTool.config = Config;
+
+ bool inBuild = false;
+ VCFilterFile info;
+ for (int i = 0; i < Files.count(); ++i) {
+ if (Files.at(i).file == filename) {
+ info = Files.at(i);
+ inBuild = true;
+ }
+ }
+ inBuild &= !info.excludeFromBuild;
+
+ if (inBuild) {
+ addExtraCompiler(info);
+ if(Project->usePCH)
+ modifyPCHstage(info.file);
+ } else {
+ // Excluded files uses an empty compiler stage
+ if(info.excludeFromBuild)
+ useCompilerTool = true;
+ }
+
+ // Actual XML output ----------------------------------
+ if(useCustomBuildTool || useCompilerTool || !inBuild) {
+ xml << tag(_FileConfiguration)
+ << attr(_Name, (*Config).Name)
+ << (!inBuild ? attrS(_ExcludedFromBuild, "true") : noxml());
+ if (useCustomBuildTool)
+ xml << CustomBuildTool;
+ if (useCompilerTool)
+ xml << CompilerTool;
+ xml << closetag(_FileConfiguration);
+ }
+}
+
+XmlOutput &operator<<(XmlOutput &xml, VCFilter &tool)
+{
+ if(!tool.Files.count())
+ return xml;
+
+ 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(_File)
+ << attrS(_RelativePath, Option::fixPathToLocalOS(info.file))
+ << data(); // In case no custom builds, to avoid "/>" endings
+ tool.outputFileConfig(xml, tool.Files.at(i).file);
+ xml << closetag(_File);
+ }
+ if (!tool.Name.isEmpty())
+ xml << closetag(_Filter);
+ return xml;
+}
+
+// VCProjectSingleConfig --------------------------------------------
+VCFilter nullFilter;
+VCFilter& VCProjectSingleConfig::filterForExtraCompiler(const QString &compilerName)
+{
+ for (int i = 0; i < ExtraCompilersFiles.count(); ++i)
+ if (ExtraCompilersFiles.at(i).Name == compilerName)
+ return ExtraCompilersFiles[i];
+ return nullFilter;
+}
+
+
+XmlOutput &operator<<(XmlOutput &xml, const 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)
+ << tool.Configuration;
+ xml << closetag(_Configurations)
+ << tag(_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;
+ tempProj.outputFilter(xml, "Sources");
+ tempProj.outputFilter(xml, "Headers");
+ tempProj.outputFilter(xml, "GeneratedFiles");
+ tempProj.outputFilter(xml, "LexYaccFiles");
+ tempProj.outputFilter(xml, "TranslationFiles");
+ tempProj.outputFilter(xml, "FormFiles");
+ tempProj.outputFilter(xml, "ResourceFiles");
+ for (int x = 0; x < tempProj.ExtraCompilers.count(); ++x) {
+ tempProj.outputFilter(xml, tempProj.ExtraCompilers.at(x));
+ }
+ tempProj.outputFilter(xml, "RootFiles");
+ xml << closetag(_Files)
+ << tag(_Globals)
+ << data(); // No "/>" end tag
+ return xml;
+}
+
+
+// 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
+ tool.outputFileConfigs(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) {
+ tool.outputFileConfigs(xml, (*it), filter);
+ }
+ }
+}
+
+
+// VCProject --------------------------------------------------------
+// Output all configurations (by filtername) for a file (by info)
+// A filters config output is in VCFilter.outputFileConfig()
+void VCProject::outputFileConfigs(XmlOutput &xml,
+// VCProjectSingleConfig::FilterTypes type
+ const VCFilterFile &info,
+ const QString &filtername)
+{
+ xml << tag(_File)
+ << attrS(_RelativePath, Option::fixPathToLocalOS(info.file));
+ for (int i = 0; i < SingleProjects.count(); ++i) {
+ VCFilter filter;
+ if (filtername == "RootFiles") {
+ filter = SingleProjects.at(i).RootFiles;
+ } else if (filtername == "Sources") {
+ filter = SingleProjects.at(i).SourceFiles;
+ } else if (filtername == "Headers") {
+ filter = SingleProjects.at(i).HeaderFiles;
+ } else if (filtername == "GeneratedFiles") {
+ filter = SingleProjects.at(i).GeneratedFiles;
+ } else if (filtername == "LexYaccFiles") {
+ filter = SingleProjects.at(i).LexYaccFiles;
+ } else if (filtername == "TranslationFiles") {
+ filter = SingleProjects.at(i).TranslationFiles;
+ } else if (filtername == "FormFiles") {
+ filter = SingleProjects.at(i).FormFiles;
+ } else if (filtername == "ResourceFiles") {
+ filter = SingleProjects.at(i).ResourceFiles;
+ } else {
+ // ExtraCompilers
+ filter = SingleProjects[i].filterForExtraCompiler(filtername);
+ }
+
+ if (filter.Config) // only if the filter is not empty
+ filter.outputFileConfig(xml, info.file);
+ }
+ xml << closetag(_File);
+}
+
+// outputs a given filter for all existing configurations of a project
+void VCProject::outputFilter(XmlOutput &xml,
+// VCProjectSingleConfig::FilterTypes type
+ const QString &filtername)
+{
+ Node *root;
+ if (SingleProjects.at(0).flat_files)
+ root = new FlatNode;
+ else
+ root = new TreeNode;
+
+ QString name, extfilter, guid;
+ triState parse;
+
+ for (int i = 0; i < SingleProjects.count(); ++i) {
+ VCFilter filter;
+ if (filtername == "RootFiles") {
+ filter = SingleProjects.at(i).RootFiles;
+ } else if (filtername == "Sources") {
+ filter = SingleProjects.at(i).SourceFiles;
+ } else if (filtername == "Headers") {
+ filter = SingleProjects.at(i).HeaderFiles;
+ } else if (filtername == "GeneratedFiles") {
+ filter = SingleProjects.at(i).GeneratedFiles;
+ } else if (filtername == "LexYaccFiles") {
+ filter = SingleProjects.at(i).LexYaccFiles;
+ } else if (filtername == "TranslationFiles") {
+ filter = SingleProjects.at(i).TranslationFiles;
+ } else if (filtername == "FormFiles") {
+ filter = SingleProjects.at(i).FormFiles;
+ } else if (filtername == "ResourceFiles") {
+ filter = SingleProjects.at(i).ResourceFiles;
+ } else {
+ // ExtraCompilers
+ filter = 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, "", *this, filtername); // output root tree
+ if (!name.isEmpty())
+ xml << closetag(_Filter);
+}
+
+XmlOutput &operator<<(XmlOutput &xml, VCProject &tool)
+{
+ if (tool.SingleProjects.count() == 0) {
+ warn_msg(WarnLogic, "Generator: .NET: no single project in merge project, no output");
+ return xml;
+ }
+
+ 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)
+ xml << tool.SingleProjects.at(i).Configuration;
+ xml << closetag(_Configurations)
+ << tag(_Files);
+ tool.outputFilter(xml, "Sources");
+ tool.outputFilter(xml, "Headers");
+ tool.outputFilter(xml, "GeneratedFiles");
+ tool.outputFilter(xml, "LexYaccFiles");
+ tool.outputFilter(xml, "TranslationFiles");
+ tool.outputFilter(xml, "FormFiles");
+ tool.outputFilter(xml, "ResourceFiles");
+ for (int x = 0; x < tool.ExtraCompilers.count(); ++x) {
+ tool.outputFilter(xml, tool.ExtraCompilers.at(x));
+ }
+ tool.outputFilter(xml, "RootFiles");
+ xml << closetag(_Files)
+ << tag(_Globals)
+ << data(); // No "/>" end tag
+ return xml;
+}
+
+QT_END_NAMESPACE
diff --git a/qmake/generators/win32/msvc_objectmodel.h b/qmake/generators/win32/msvc_objectmodel.h
new file mode 100644
index 0000000..e3f56f6
--- /dev/null
+++ b/qmake/generators/win32/msvc_objectmodel.h
@@ -0,0 +1,1078 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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
+};
+
+/*
+ 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
+};
+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
+};
+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 {
+ 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());
+ }
+};
+
+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 GlobalOptimizations;
+ triState IgnoreStandardIncludePath;
+ triState ImproveFloatingPointConsistency;
+ inlineExpansionOption InlineFunctionExpansion;
+ triState KeepComments;
+ triState MinimalRebuild;
+ QString ObjectFile;
+ 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 WarnAsError;
+ warningLevelOption WarningLevel;
+ triState WholeProgramOptimization;
+ useOfArchitecture CompileForArchitecture;
+ triState InterworkCalls;
+ 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;
+ 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 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 TurnOffAssemblyGeneration;
+ QString TypeLibraryFile;
+ qlonglong TypeLibraryResourceID;
+ QString Version;
+ 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;
+ 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;
+};
+
+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;
+};
+
+class VCDeploymentTool
+{
+public:
+ // Functions
+ VCDeploymentTool();
+ virtual ~VCDeploymentTool() {}
+
+ // Variables
+ QString DeploymentTag;
+ QString RemoteDirectory;
+ RegisterDeployOption RegisterOutput;
+ QString AdditionalFiles;
+};
+
+class VCEventTool : public VCToolBase
+{
+protected:
+ // Functions
+ VCEventTool() : ExcludedFromBuild(unset){};
+ virtual ~VCEventTool(){}
+ bool parseOption(const char*){ return false; };
+
+public:
+ // Variables
+ QString CommandLine;
+ QString Description;
+ triState ExcludedFromBuild;
+ 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;
+ 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);
+ void outputFileConfig(XmlOutput &xml, const QString &filename);
+
+ // 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;
+
+private:
+ friend XmlOutput &operator<<(XmlOutput &xml, VCFilter &tool);
+};
+
+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;
+
+ // Functions
+ void outputFilter(XmlOutput &xml,
+// VCProjectSingleConfig::FilterTypes type,
+ const QString &filtername);
+
+ void outputFileConfigs(XmlOutput &xml,
+// VCProjectSingleConfig::FilterTypes type,
+ const VCFilterFile &info,
+ const QString &filtername);
+};
+
+XmlOutput &operator<<(XmlOutput &, const VCCLCompilerTool &);
+XmlOutput &operator<<(XmlOutput &, const VCLinkerTool &);
+XmlOutput &operator<<(XmlOutput &, const VCMIDLTool &);
+XmlOutput &operator<<(XmlOutput &, const VCCustomBuildTool &);
+XmlOutput &operator<<(XmlOutput &, const VCLibrarianTool &);
+XmlOutput &operator<<(XmlOutput &, const VCResourceCompilerTool &);
+XmlOutput &operator<<(XmlOutput &, const VCEventTool &);
+XmlOutput &operator<<(XmlOutput &, const VCDeploymentTool &);
+XmlOutput &operator<<(XmlOutput &, const VCConfiguration &);
+XmlOutput &operator<<(XmlOutput &, VCFilter &);
+XmlOutput &operator<<(XmlOutput &, const VCProjectSingleConfig &);
+XmlOutput &operator<<(XmlOutput &, VCProject &);
+
+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 0000000..08159b0
--- /dev/null
+++ b/qmake/generators/win32/msvc_vcproj.cpp
@@ -0,0 +1,1785 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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
+//#define DEBUG_PROJECT_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>
+
+QT_BEGIN_NAMESPACE
+
+struct {
+ DotNET version;
+ const char *versionStr;
+ const char *regKey;
+} dotNetCombo[] = {
+#ifdef Q_OS_WIN64
+ {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
+ {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, "", ""},
+};
+
+static QString keyPath(const QString &rKey)
+{
+ int idx = rKey.lastIndexOf(QLatin1Char('\\'));
+ if (idx == -1)
+ return QString();
+ return rKey.left(idx + 1);
+}
+
+static QString keyName(const QString &rKey)
+{
+ int idx = rKey.lastIndexOf(QLatin1Char('\\'));
+ if (idx == -1)
+ return rKey;
+
+ QString res(rKey.mid(idx + 1));
+ if (res == "Default" || res == ".")
+ res = "";
+ return res;
+}
+
+static QString readRegistryKey(HKEY parentHandle, const QString &rSubkey)
+{
+
+ QString rSubkeyName = keyName(rSubkey);
+ QString rSubkeyPath = keyPath(rSubkey);
+
+ HKEY handle = 0;
+ LONG res;
+ QT_WA( {
+ res = RegOpenKeyExW(parentHandle, (WCHAR*)rSubkeyPath.utf16(),
+ 0, KEY_READ, &handle);
+ } , {
+ res = RegOpenKeyExA(parentHandle, rSubkeyPath.toLocal8Bit(),
+ 0, KEY_READ, &handle);
+ } );
+
+ if (res != ERROR_SUCCESS)
+ return QString();
+
+ // get the size and type of the value
+ DWORD dataType;
+ DWORD dataSize;
+ QT_WA( {
+ res = RegQueryValueExW(handle, (WCHAR*)rSubkeyName.utf16(), 0, &dataType, 0, &dataSize);
+ }, {
+ res = RegQueryValueExA(handle, rSubkeyName.toLocal8Bit(), 0, &dataType, 0, &dataSize);
+ } );
+ if (res != ERROR_SUCCESS) {
+ RegCloseKey(handle);
+ return QString();
+ }
+
+ // get the value
+ QByteArray data(dataSize, 0);
+ QT_WA( {
+ res = RegQueryValueExW(handle, (WCHAR*)rSubkeyName.utf16(), 0, 0,
+ reinterpret_cast<unsigned char*>(data.data()), &dataSize);
+ }, {
+ res = RegQueryValueExA(handle, rSubkeyName.toLocal8Bit(), 0, 0,
+ reinterpret_cast<unsigned char*>(data.data()), &dataSize);
+ } );
+ if (res != ERROR_SUCCESS) {
+ RegCloseKey(handle);
+ return QString();
+ }
+
+ QString result;
+ switch (dataType) {
+ case REG_EXPAND_SZ:
+ case REG_SZ: {
+ QT_WA( {
+ result = QString::fromUtf16(((const ushort*)data.constData()));
+ }, {
+ result = QString::fromLatin1(data.constData());
+ } );
+ break;
+ }
+
+ case REG_MULTI_SZ: {
+ QStringList l;
+ int i = 0;
+ for (;;) {
+ QString s;
+ QT_WA( {
+ s = QString::fromUtf16((const ushort*)data.constData() + i);
+ }, {
+ s = QString::fromLatin1(data.constData() + i);
+ } );
+ i += s.length() + 1;
+
+ if (s.isEmpty())
+ break;
+ l.append(s);
+ }
+ result = l.join(", ");
+ break;
+ }
+
+ case REG_NONE:
+ case REG_BINARY: {
+ QT_WA( {
+ result = QString::fromUtf16((const ushort*)data.constData(), data.size()/2);
+ }, {
+ result = QString::fromLatin1(data.constData(), data.size());
+ } );
+ break;
+ }
+
+ case REG_DWORD_BIG_ENDIAN:
+ case REG_DWORD: {
+ Q_ASSERT(data.size() == sizeof(int));
+ int i;
+ memcpy((char*)&i, data.constData(), sizeof(int));
+ result = QString::number(i);
+ break;
+ }
+
+ default:
+ qWarning("QSettings: unknown data %d type in windows registry", dataType);
+ break;
+ }
+
+ RegCloseKey(handle);
+ return result;
+}
+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 = 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 = 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";
+const char _slnHeader90[] = "Microsoft Visual Studio Solution File, Format Version 10.00";
+ // 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)
+{
+}
+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);
+ 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 = unescapeFilePath(project->first("QMAKE_ORIG_TARGET"));
+ 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);
+ 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;
+}
+
+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 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;
+
+ QStringList subdirs = project->values("SUBDIRS");
+ 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");
+
+ for(int i = 0; i < subdirs.size(); ++i) {
+ QString tmp = subdirs.at(i);
+ if(!project->isEmpty(tmp + ".file")) {
+ if(!project->isEmpty(tmp + ".subdir"))
+ warn_msg(WarnLogic, "Cannot assign both file and subdir for subdir %s",
+ tmp.toLatin1().constData());
+ tmp = project->first(tmp + ".file");
+ } else if(!project->isEmpty(tmp + ".subdir")) {
+ tmp = project->first(tmp + ".subdir");
+ }
+ 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() + ".pro";
+ 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") {
+ QStringList tmp_proj_subdirs = tmp_proj.variables()["SUBDIRS"];
+ for(int x = 0; x < tmp_proj_subdirs.size(); ++x) {
+ QString tmpdir = tmp_proj_subdirs.at(x);
+ if(!tmp_proj.isEmpty(tmpdir + ".file")) {
+ if(!tmp_proj.isEmpty(tmpdir + ".subdir"))
+ warn_msg(WarnLogic, "Cannot assign both file and subdir for subdir %s",
+ tmpdir.toLatin1().constData());
+ tmpdir = tmp_proj.first(tmpdir + ".file");
+ } else if(!tmp_proj.isEmpty(tmpdir + ".subdir")) {
+ tmpdir = tmp_proj.first(tmpdir + ".subdir");
+ }
+ 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) {
+ 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_ORIG_TARGET].vcproj
+ QString vcproj = unescapeFilePath(fixFilename(tmp_vcproj.project->first("QMAKE_ORIG_TARGET")) + 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("QMAKE_LIBS");
+ 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;
+ if(project->first("TEMPLATE") == "vcsubdirs") { //too much work for subdirs
+ init_flag = true;
+ 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();
+ 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)
+{
+ VcprojGenerator *otherVC = static_cast<VcprojGenerator*>(other);
+ if (!otherVC) {
+ warn_msg(WarnLogic, "VcprojGenerator: Cannot merge other types of projects! (ignored)");
+ return false;
+ }
+ 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 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.Name = project->values("BUILD_NAME").join(" ");
+ if (conf.Name.isEmpty())
+ conf.Name = isDebug ? "Debug" : "Release";
+ 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.OutputDirectory = ".";
+ conf.PrimaryOutput = project->first("PrimaryOutput");
+ 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 ;
+ // 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");
+ // Minimal build option triggers an Internal Compiler Error
+ // when used in conjunction with /FI and /Yu, so remove it
+ 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("debug")){
+ // Debug version
+ conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS"));
+ conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_DEBUG"));
+ if((projectTarget == Application) || (projectTarget == StaticLib))
+ conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_MT_DBG"));
+ else
+ conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_MT_DLLDBG"));
+ } else {
+ // Release version
+ conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS"));
+ conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_RELEASE"));
+ conf.compiler.PreprocessorDefinitions += "QT_NO_DEBUG";
+ conf.compiler.PreprocessorDefinitions += "NDEBUG";
+ if((projectTarget == Application) || (projectTarget == StaticLib))
+ conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_MT"));
+ else
+ conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_MT_DLL"));
+ }
+
+ // Common for both release and debug
+ if(project->isActiveConfig("warn_off"))
+ conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_WARN_OFF"));
+ else if(project->isActiveConfig("warn_on"))
+ conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_WARN_ON"));
+ if(project->isActiveConfig("windows"))
+ conf.compiler.PreprocessorDefinitions += project->values("MSVCPROJ_WINCONDEF");
+
+ // Can this be set for ALL configs?
+ // If so, use qmake.conf!
+ if(projectTarget == SharedLib)
+ conf.compiler.PreprocessorDefinitions += "_WINDOWS";
+
+ 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 = project->first("DESTDIR");
+ if(conf.librarian.OutputFile.isEmpty())
+ conf.librarian.OutputFile = ".\\";
+
+ if(!conf.librarian.OutputFile.endsWith("\\"))
+ conf.librarian.OutputFile += '\\';
+
+ 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("MSVCPROJ_LFLAGS"));
+
+ 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;
+ }
+ }
+
+ switch (projectTarget) {
+ case Application:
+ conf.linker.OutputFile = project->first("DESTDIR");
+ break;
+ case SharedLib:
+ conf.linker.parseOptions(project->values("MSVCPROJ_LIBOPTIONS"));
+ conf.linker.OutputFile = project->first("DESTDIR");
+ break;
+ case StaticLib: //unhandled - added to remove warnings..
+ break;
+ }
+
+ if(conf.linker.OutputFile.isEmpty())
+ conf.linker.OutputFile = ".\\";
+
+ if(!conf.linker.OutputFile.endsWith("\\"))
+ conf.linker.OutputFile += '\\';
+
+ conf.linker.OutputFile += project->first("MSVCPROJ_TARGET");
+
+ if(project->isActiveConfig("debug")){
+ conf.linker.parseOptions(project->values("QMAKE_LFLAGS_DEBUG"));
+ } else {
+ conf.linker.parseOptions(project->values("QMAKE_LFLAGS_RELEASE"));
+ }
+
+ if(project->isActiveConfig("dll")){
+ conf.linker.parseOptions(project->values("QMAKE_LFLAGS_QT_DLL"));
+ }
+
+ if(project->isActiveConfig("console")){
+ conf.linker.parseOptions(project->values("QMAKE_LFLAGS_CONSOLE"));
+ } else {
+ conf.linker.parseOptions(project->values("QMAKE_LFLAGS_WINDOWS"));
+ }
+
+}
+
+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 = project->first("DESTDIR") + "/$(InputName).res";
+}
+
+
+void VcprojGenerator::initIDLTool()
+{
+}
+
+void VcprojGenerator::initCustomBuildTool()
+{
+}
+
+void VcprojGenerator::initPreBuildEventTools()
+{
+}
+
+QString VcprojGenerator::fixCommandLine(DotNET version, const QString &input) const
+{
+ QString result = input;
+
+ if (version >= NET2005)
+ result = result.replace(QLatin1Char('\n'), QLatin1String("&#x000D;&#x000A;"));
+
+ return result;
+}
+
+void VcprojGenerator::initPostBuildEventTools()
+{
+ VCConfiguration &conf = vcProject.Configuration;
+ if(!project->values("QMAKE_POST_LINK").isEmpty()) {
+ QString cmdline = fixCommandLine(conf.CompilerVersion, var("QMAKE_POST_LINK"));
+ conf.postBuild.CommandLine = cmdline;
+ if (conf.CompilerVersion < NET2005)
+ cmdline = cmdline.replace("\n", "&&");
+ conf.postBuild.Description = cmdline;
+ }
+
+ 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 + " \"$(TargetPath)\"\n" +
+ (!conf.postBuild.CommandLine.isEmpty() ? " && " : ""));
+
+ if(!project->values("MSVCPROJ_COPY_DLL").isEmpty()) {
+ if(!conf.postBuild.CommandLine.isEmpty())
+ conf.postBuild.CommandLine += " && ";
+ conf.postBuild.Description += var("MSVCPROJ_COPY_DLL_DESC");
+ conf.postBuild.CommandLine += var("MSVCPROJ_COPY_DLL");
+ }
+}
+
+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 = targetPath.mid(0,targetPath.size()-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 the path does not exist, skip it
+ if (devicePath.isEmpty())
+ continue;
+ // 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
+ foreach(QString source, project->values(item + ".sources")) {
+ 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()) {
+ QString cmdline = fixCommandLine(conf.CompilerVersion, var("QMAKE_PRE_LINK"));
+ conf.preLink.Description = cmdline;
+ conf.preLink.CommandLine = cmdline;
+ }
+}
+
+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)) {
+ 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(' '));
+ }
+ }
+ }
+ 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);
+ }
+}
+
+/* \internal
+ Sets up all needed variables from the environment and all the different caches and .conf files
+*/
+
+void VcprojGenerator::initOld()
+{
+ if(init_flag)
+ return;
+
+ init_flag = true;
+ QStringList::Iterator it;
+
+ // Decode version, and add it to $$MSVCPROJ_VERSION --------------
+ 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("MSVCPROJ_VERSION").append("/VERSION:" + major + "." + minor);
+ project->values("QMAKE_LFLAGS").append("/VERSION:" + major + "." + minor);
+ }
+
+ project->values("QMAKE_LIBS") += escapeFilePaths(project->values("LIBS"));
+
+ // Get filename w/o extension -----------------------------------
+ QString msvcproj_project = "";
+ QString targetfilename = "";
+ if(!project->isEmpty("TARGET")) {
+ project->values("TARGET") = unescapeFilePaths(project->values("TARGET"));
+ targetfilename = msvcproj_project = project->first("TARGET");
+ }
+
+ // Init base class too -------------------------------------------
+ MakefileGenerator::init();
+
+ if(msvcproj_project.isEmpty())
+ msvcproj_project = Option::output.fileName();
+
+ msvcproj_project = msvcproj_project.right(msvcproj_project.length() - msvcproj_project.lastIndexOf("\\") - 1);
+ msvcproj_project = msvcproj_project.left(msvcproj_project.lastIndexOf("."));
+ msvcproj_project.replace(QRegExp("-"), "");
+
+ project->values("MSVCPROJ_PROJECT").append(msvcproj_project);
+ QStringList &proj = project->values("MSVCPROJ_PROJECT");
+
+ for(it = proj.begin(); it != proj.end(); ++it)
+ (*it).replace(QRegExp("\\.[a-zA-Z0-9_]*$"), "");
+
+ // SUBSYSTEM -----------------------------------------------------
+ if(!project->values("QMAKE_APP_FLAG").isEmpty()) {
+ project->values("MSVCPROJ_TEMPLATE").append("win32app" + project->first("VCPROJ_EXTENSION"));
+ if(project->isActiveConfig("console")) {
+ project->values("MSVCPROJ_CONSOLE").append("CONSOLE");
+ project->values("MSVCPROJ_WINCONDEF").append("_CONSOLE");
+ project->values("MSVCPROJ_VCPROJTYPE").append("0x0103");
+ project->values("MSVCPROJ_SUBSYSTEM").append("CONSOLE");
+ } else {
+ project->values("MSVCPROJ_CONSOLE").clear();
+ project->values("MSVCPROJ_WINCONDEF").append("_WINDOWS");
+ project->values("MSVCPROJ_VCPROJTYPE").append("0x0101");
+ project->values("MSVCPROJ_SUBSYSTEM").append("WINDOWS");
+ }
+ }
+
+ // $$QMAKE.. -> $$MSVCPROJ.. -------------------------------------
+ project->values("MSVCPROJ_LIBS") += project->values("QMAKE_LIBS");
+ project->values("MSVCPROJ_LFLAGS") += project->values("QMAKE_LFLAGS");
+ if(!project->values("QMAKE_LIBDIR").isEmpty()) {
+ QStringList strl = project->values("QMAKE_LIBDIR");
+ QStringList::iterator stri;
+ for(stri = strl.begin(); stri != strl.end(); ++stri) {
+ if(!(*stri).startsWith("/LIBPATH:"))
+ (*stri).prepend("/LIBPATH:");
+ }
+ project->values("MSVCPROJ_LFLAGS") += strl;
+ }
+ project->values("MSVCPROJ_CXXFLAGS") += project->values("QMAKE_CXXFLAGS");
+ 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);
+ }
+
+ if (!project->values("DEF_FILE").isEmpty())
+ project->values("MSVCPROJ_LFLAGS").append("/DEF:"+project->first("DEF_FILE"));
+
+ project->values("QMAKE_INTERNAL_PRL_LIBS") << "MSVCPROJ_LIBS";
+
+ // Verbose output if "-d -d"...
+ outputVariables();
+}
+
+// ------------------------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------------------------
+
+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 hypenfind = ofile.indexOf('-', slashfind);
+ while (hypenfind != -1 && slashfind < hypenfind) {
+ ofile = ofile.replace(hypenfind, 1, '_');
+ hypenfind = ofile.indexOf('-', hypenfind + 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))) &&
+ !exists((ret = (QString(qgetenv("HOME")) + "/.tmake/" + file))))
+ return "";
+ debug_msg(1, "Generator: MSVC.NET: Found template \'%s\'", ret.toLatin1().constData());
+ return ret;
+}
+
+
+void VcprojGenerator::processPrlVariable(const QString &var, const QStringList &l)
+{
+ if(var == "QMAKE_PRL_DEFINES") {
+ QStringList &out = project->values("MSVCPROJ_DEFINES");
+ for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
+ if(out.indexOf((*it)) == -1)
+ out.append((" /D " + *it));
+ }
+ } else {
+ MakefileGenerator::processPrlVariable(var, l);
+ }
+}
+
+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", it.key().toLatin1().constData(), it.data().join(" | ").toLatin1().constData());
+#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 0000000..9e7d725
--- /dev/null
+++ b/qmake/generators/win32/msvc_vcproj.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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();
+ void writeSubDirs(QTextStream &t);
+
+ 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;
+
+protected:
+ 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 void processPrlVariable(const QString &, const QStringList &);
+ 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();
+
+ Target projectTarget;
+
+ // Used for single project
+ VCProjectSingleConfig vcProject;
+
+ // Holds all configurations for glue (merged) project
+ QList<VcprojGenerator*> mergedProjects;
+
+private:
+ QString fixCommandLine(DotNET version, const QString &input) const;
+ QUuid getProjectUUID(const QString &filename=QString());
+ QUuid increaseUUID(const QUuid &id);
+ friend class VCFilter;
+};
+
+inline VcprojGenerator::~VcprojGenerator()
+{ }
+
+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/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp
new file mode 100644
index 0000000..60a27be
--- /dev/null
+++ b/qmake/generators/win32/winmakefile.cpp
@@ -0,0 +1,821 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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")) {
+ QDir dir(bd);
+ QStringList entries = dir.entryList();
+ 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;
+ 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->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("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);
+ }
+}
+
+void Win32MakefileGenerator::fixTargetExt()
+{
+ 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") + ".dll");
+ else
+ project->values("TARGET_EXT").append(".lib");
+}
+
+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 << "\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 && rcFile.open(QFile::WriteOnly)) {
+ 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())
+ if(project->isActiveConfig("staticlib"))
+ project->values("RES_FILE").first().prepend(fileInfo(project->values("DESTDIR").first()).absoluteFilePath() + Option::dir_sep);
+ else
+ project->values("RES_FILE").first().prepend(project->values("OBJECTS_DIR").first() + Option::dir_sep);
+ 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 = " << (project->isEmpty("QMAKE_QMAKE") ? QString("qmake") :
+ Option::fixPathToTargetOS(var("QMAKE_QMAKE"), false)) << 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 (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 compatability 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 << "\n\t" << "-$(COPY_FILE) \"$(DESTDIR_TARGET)\" " << Option::fixPathToTargetOS(*dlldir, false);
+ }
+ }
+ t << endl << 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") << 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("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 0000000..c8e32f8
--- /dev/null
+++ b/qmake/generators/win32/winmakefile.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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"); }
+
+QT_END_NAMESPACE
+
+#endif // WINMAKEFILE_H