📄 msvc_vcproj.cpp
字号:
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 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 VcprojGenerator tmp_vcproj; tmp_vcproj.setNoIO(true); tmp_vcproj.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 vcproj = unescapeFilePath(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(!exists(qmake_getpwd() + Option::dir_sep + vcproj)) { warn_msg(WarnLogic, "Ignored (not found) '%s'", QString(qmake_getpwd() + Option::dir_sep + vcproj).toLatin1().constData()); goto nextfile; // # Dirty! } VcsolutionDepend *newDep = new VcsolutionDepend; newDep->vcprojFile = fileFixify(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(qmake_getpwd() + 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" &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -