⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 msvc_vcproj.cpp

📁 Trolltech公司发布的基于C++图形开发环境
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/****************************************************************************** $Id: qt/msvc_vcproj.cpp   3.3.4   edited Jan 12 12:51 $**** Implementation of VcprojGenerator class.**** Copyright (C) 1992-2003 Trolltech AS.  All rights reserved.**** This file is part of qmake.**** This file may be distributed under the terms of the Q Public License** as defined by Trolltech AS of Norway and appearing in the file** LICENSE.QPL included in the packaging of this file.**** This file may be distributed and/or modified under the terms of the** GNU General Public License version 2 as published by the Free Software** Foundation and appearing in the file LICENSE.GPL included in the** packaging of this file.**** Licensees holding valid Qt Enterprise Edition licenses may use this** file in accordance with the Qt Commercial License Agreement provided** with the Software.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.**** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for**   information about Qt Commercial License Agreements.** See http://www.trolltech.com/qpl/ for QPL licensing information.** See http://www.trolltech.com/gpl/ for GPL licensing information.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#include "msvc_vcproj.h"#include "option.h"#include "qtmd5.h" // SG's MD5 addon#include <qdir.h>#include <qregexp.h>#include <qdict.h>#include <quuid.h>#include <stdlib.h>#include <qsettings.h>//#define DEBUG_SOLUTION_GEN//#define DEBUG_PROJECT_GEN// Registry keys for .NET version detection -------------------------const char* _regNet2002		= "Microsoft\\VisualStudio\\7.0\\Setup\\VC\\ProductDir";const char* _regNet2003		= "Microsoft\\VisualStudio\\7.1\\Setup\\VC\\ProductDir";bool use_net2003_version(){#ifndef Q_OS_WIN32    return FALSE; // Always generate 7.0 versions on other platforms#else    // Only search for the version once    static int current_version = -1;    if (current_version!=-1)	return (current_version==71);    // Fallback to .NET 2002    current_version = 70;    // Get registry entries for both versions    bool ok = FALSE;    QSettings setting;    QString path2002 = setting.readEntry(_regNet2002);    QString path2003 = setting.readEntry(_regNet2003);    if ( path2002.isNull() || path2003.isNull() ) {	// Only have one MSVC, so use that one	current_version = (path2003.isNull() ? 70 : 71);    } else {	// Have both, so figure out the current	QString paths = getenv("PATH");	QStringList pathlist = QStringList::split(";", paths.lower());	path2003 = path2003.lower();	QStringList::iterator it;	for(it=pathlist.begin(); it!=pathlist.end(); ++it) {	    if ((*it).contains(path2003)) {		current_version = 71;	    } else if ((*it).contains(path2002)		       && current_version == 71) {		fprintf( stderr, "Both .NET 2002 & .NET 2003 directories for VC found in you PATH variable!\nFallback to .NET 2002 project generation" );		current_version = 70;		break;	    }	}    }    return (current_version==71);#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";				  // 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"				  "\n\t\tConfigName.1 = Release"				  "\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.ActiveCfg = Release|Win32";const char* _slnProjRelConfTag2	= ".Release.Build.0 = Release|Win32";const char* _slnProjDbgConfTag1	= ".Debug.ActiveCfg = Debug|Win32";const char* _slnProjDbgConfTag2	= ".Debug.Build.0 = Debug|Win32";const char* _slnProjConfEnd	= "\n\tEndGlobalSection";const char* _slnExtSections	= "\n\tGlobalSection(ExtensibilityGlobals) = postSolution"				  "\n\tEndGlobalSection"				  "\n\tGlobalSection(ExtensibilityAddIns) = postSolution"				  "\n\tEndGlobalSection";// ------------------------------------------------------------------VcprojGenerator::VcprojGenerator(QMakeProject *p) : Win32MakefileGenerator(p), init_flag(FALSE){}/* \internal    Generates a project file for the given profile.    Options are either a Visual Studio projectfiles, or    solutionfiles by parsing recursive projectdirectories.*/bool VcprojGenerator::writeMakefile(QTextStream &t){    // Check if all requirements are fullfilled    if(!project->variables()["QMAKE_FAILED_REQUIREMENTS"].isEmpty()) {	fprintf(stderr, "Project file not generated because all requirements not met:\n\t%s\n",		var("QMAKE_FAILED_REQUIREMENTS").latin1());	return TRUE;    }    // Generate project file    if(project->first("TEMPLATE") == "vcapp" ||       project->first("TEMPLATE") == "vclib") {        debug_msg(1, "Generator: MSVC.NET: Writing project file" );	t << vcProject;	return TRUE;    }    // Generate solution file    else if(project->first("TEMPLATE") == "vcsubdirs") {        debug_msg(1, "Generator: MSVC.NET: Writing solution file" );	writeSubDirs(t);	return TRUE;    }    return FALSE;}struct VcsolutionDepend {    QString uuid;    QString vcprojFile, orig_target, target;    ::target targetType;    bool debugBuild;    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.isNull()) {	QString abspath = filename.isNull()?project->first("QMAKE_MAKEFILE"):filename;	qtMD5(abspath.utf8(), (unsigned char*)(&uuid));	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().upper().latin1());    }    // Store GUID in variable-space    project->values("GUID") = uuid.toString().upper();    return uuid;}QUuid VcprojGenerator::increaseUUID( const QUuid &id ){    QUuid result( id );    Q_LONG dataFirst = (result.data4[0] << 24) +		       (result.data4[1] << 16) +		       (result.data4[2] << 8) +                        result.data4[3];    Q_LONG 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){    if(project->first("TEMPLATE") == "subdirs") {	writeHeader(t);	Win32MakefileGenerator::writeSubDirs(t);	return;    }    t << (use_net2003_version() ? _slnHeader71 : _slnHeader70);    QDict<VcsolutionDepend> solution_depends;    QPtrList<VcsolutionDepend> solution_cleanup;    solution_cleanup.setAutoDelete(TRUE);    QStringList subdirs = project->variables()["SUBDIRS"];    QString oldpwd = QDir::currentDirPath();    for(QStringList::Iterator it = subdirs.begin(); it != subdirs.end(); ++it) {	QFileInfo fi(Option::fixPathToLocalOS((*it), TRUE));	if(fi.exists()) {	    if(fi.isDir()) {		QString profile = (*it);		if(!profile.endsWith(Option::dir_sep))		    profile += Option::dir_sep;		profile += fi.baseName() + ".pro";		subdirs.append(profile);	    } else {		QMakeProject tmp_proj;		QString dir = fi.dirPath(), fn = fi.fileName();		if(!dir.isEmpty()) {		    if(!QDir::setCurrent(dir))			fprintf(stderr, "Cannot find directory: %s\n", dir.latin1());		}		if(tmp_proj.read(fn, oldpwd)) {		    if(tmp_proj.first("TEMPLATE") == "vcsubdirs") {			subdirs += fileFixify(tmp_proj.variables()["SUBDIRS"]);		    } 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			VcprojGenerator tmp_vcproj(&tmp_proj);			tmp_vcproj.setNoIO(TRUE);			tmp_vcproj.init();			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.data().isEmpty())				    debug_msg(1, "%s: %s === %s", fn.latin1(), it.key().latin1(),						it.data().join(" :: ").latin1());			    }			}			// We assume project filename is [QMAKE_ORIG_TARGET].vcproj			QString vcproj = fixFilename(tmp_vcproj.project->first("QMAKE_ORIG_TARGET")) + project->first("VCPROJ_EXTENSION");			// If file doesn't exsist, then maybe the users configuration			// doesn't allow it to be created. Skip to next...			if(!QFile::exists(QDir::currentDirPath() + Option::dir_sep + vcproj)) {			    warn_msg(WarnLogic, "Ignored (not found) '%s'", QString(QDir::currentDirPath() + Option::dir_sep + vcproj).latin1() );			    goto nextfile; // # Dirty!			}			VcsolutionDepend *newDep = new VcsolutionDepend;			newDep->vcprojFile = fileFixify(vcproj);			newDep->orig_target = tmp_proj.first("QMAKE_ORIG_TARGET");			newDep->target = tmp_proj.first("MSVCPROJ_TARGET").section(Option::dir_sep, -1);			newDep->targetType = tmp_vcproj.projectTarget;			newDep->debugBuild = tmp_proj.isActiveConfig("debug");			newDep->uuid = getProjectUUID(Option::fixPathToLocalOS(QDir::currentDirPath() + QDir::separator() + vcproj)).toString().upper();			// 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 using Forms are dependent on uic.exe			if(!tmp_proj.isEmpty("FORMS"))			    newDep->dependencies << "uic.exe";			// 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 != "winspool.lib" &&				    opt != "delayimp.lib" )				{				    newDep->dependencies << opt.section(Option::dir_sep, -1);				}			    }			}#ifdef DEBUG_SOLUTION_GEN			qDebug( "Deps for %20s: [%s]", newDep->target.latin1(), newDep->dependencies.join(" :: " ).latin1() );#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:		QDir::setCurrent(oldpwd);	    }	}    }    t << _slnGlobalBeg;    t << _slnSolutionConf;    t << _slnProjDepBeg;    // Figure out dependencies    for(solution_cleanup.first(); solution_cleanup.current(); solution_cleanup.next()) {	if(solution_cleanup.current()->targetType == StaticLib)	    continue; // Shortcut, Static libs are not dep.	int cnt = 0;	for(QStringList::iterator dit = solution_cleanup.current()->dependencies.begin();	    dit != solution_cleanup.current()->dependencies.end();	    ++dit)	{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -