blob: 4ffd6528b2a0c5757530f2f3217e428ec6dcc2be [file] [log] [blame] [edit]
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "cmGlobalVisualStudio7Generator.h"
#include <algorithm>
#include <cstdio>
#include <ostream>
#include <utility>
#include <vector>
#include <cm/memory>
#include <cm/string_view>
#include <windows.h>
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmList.h"
#include "cmLocalGenerator.h"
#include "cmLocalVisualStudio7Generator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetDepend.h"
#include "cmVisualStudioGeneratorOptions.h"
#include "cmake.h"
static cmVS7FlagTable cmVS7ExtraFlagTable[] = {
// Precompiled header and related options. Note that the
// UsePrecompiledHeader entries are marked as "Continue" so that the
// corresponding PrecompiledHeaderThrough entry can be found.
{ "UsePrecompiledHeader", "YX", "Automatically Generate", "2",
cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
{ "PrecompiledHeaderThrough", "YX", "Precompiled Header Name", "",
cmVS7FlagTable::UserValueRequired },
{ "UsePrecompiledHeader", "Yu", "Use Precompiled Header", "3",
cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
{ "PrecompiledHeaderThrough", "Yu", "Precompiled Header Name", "",
cmVS7FlagTable::UserValueRequired },
{ "UsePrecompiledHeader", "Y-", "Don't use precompiled header", "0", 0 },
{ "WholeProgramOptimization", "LTCG", "WholeProgramOptimization", "true",
0 },
// Exception handling mode. If no entries match, it will be FALSE.
{ "ExceptionHandling", "GX", "enable c++ exceptions", "true", 0 },
{ "ExceptionHandling", "EHsc", "enable c++ exceptions", "true", 0 },
// The EHa option does not have an IDE setting. Let it go to false,
// and have EHa passed on the command line by leaving out the table
// entry.
{ "", "", "", "", 0 }
};
cmGlobalVisualStudio7Generator::cmGlobalVisualStudio7Generator(cmake* cm)
: cmGlobalVisualStudioGenerator(cm)
{
this->DevEnvCommandInitialized = false;
this->MarmasmEnabled = false;
this->MasmEnabled = false;
this->NasmEnabled = false;
this->ExtraFlagTable = cmVS7ExtraFlagTable;
}
cmGlobalVisualStudio7Generator::~cmGlobalVisualStudio7Generator() = default;
// Package GUID of Intel Visual Fortran plugin to VS IDE
#define CM_INTEL_PLUGIN_GUID "{B68A201D-CB9B-47AF-A52F-7EEC72E217E4}"
std::string const& cmGlobalVisualStudio7Generator::GetIntelProjectVersion()
{
if (this->IntelProjectVersion.empty()) {
// Compute the version of the Intel plugin to the VS IDE.
// If the key does not exist then use a default guess.
std::string intelVersion;
std::string vskey =
cmStrCat(this->GetRegistryBase(),
"\\Packages\\" CM_INTEL_PLUGIN_GUID ";ProductVersion");
cmSystemTools::ReadRegistryValue(vskey, intelVersion,
cmSystemTools::KeyWOW64_32);
unsigned int intelVersionNumber = ~0u;
if (sscanf(intelVersion.c_str(), "%u", &intelVersionNumber) != 1 ||
intelVersionNumber >= 11) {
// Default to latest known project file version.
intelVersion = "11.0";
} else if (intelVersionNumber == 10) {
// Version 10.x actually uses 9.10 in project files!
intelVersion = "9.10";
} else {
// Version <= 9: use ProductVersion from registry.
}
this->IntelProjectVersion = intelVersion;
}
return this->IntelProjectVersion;
}
void cmGlobalVisualStudio7Generator::EnableLanguage(
std::vector<std::string> const& lang, cmMakefile* mf, bool optional)
{
mf->AddDefinition("CMAKE_GENERATOR_RC", "rc");
mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
mf->InitCMAKE_CONFIGURATION_TYPES("Debug;Release;MinSizeRel;RelWithDebInfo");
// Create list of configurations requested by user's cache, if any.
this->cmGlobalVisualStudioGenerator::EnableLanguage(lang, mf, optional);
// if this environment variable is set, then copy it to
// a static cache entry. It will be used by
// cmLocalGenerator::ConstructScript, to add an extra PATH
// to all custom commands. This is because the VS IDE
// does not use the environment it is run in, and this allows
// for running commands and using dll's that the IDE environment
// does not know about.
std::string extraPath;
if (cmSystemTools::GetEnv("CMAKE_MSVCIDE_RUN_PATH", extraPath)) {
mf->AddCacheDefinition("CMAKE_MSVCIDE_RUN_PATH", extraPath,
"Saved environment variable CMAKE_MSVCIDE_RUN_PATH",
cmStateEnums::STATIC);
}
}
bool cmGlobalVisualStudio7Generator::FindMakeProgram(cmMakefile* mf)
{
if (!this->cmGlobalVisualStudioGenerator::FindMakeProgram(mf)) {
return false;
}
mf->AddDefinition("CMAKE_VS_DEVENV_COMMAND", this->GetDevEnvCommand());
return true;
}
std::string const& cmGlobalVisualStudio7Generator::GetDevEnvCommand()
{
if (!this->DevEnvCommandInitialized) {
this->DevEnvCommandInitialized = true;
this->DevEnvCommand = this->FindDevEnvCommand();
}
return this->DevEnvCommand;
}
std::string cmGlobalVisualStudio7Generator::FindDevEnvCommand()
{
std::string vscmd;
std::string vskey;
// Search in standard location.
vskey = cmStrCat(this->GetRegistryBase(), ";InstallDir");
if (cmSystemTools::ReadRegistryValue(vskey, vscmd,
cmSystemTools::KeyWOW64_32)) {
cmSystemTools::ConvertToUnixSlashes(vscmd);
vscmd += "/devenv.com";
if (cmSystemTools::FileExists(vscmd, true)) {
return vscmd;
}
}
// Search where VS15Preview places it.
vskey =
cmStrCat(R"(HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\SxS\VS7;)",
this->GetIDEVersion());
if (cmSystemTools::ReadRegistryValue(vskey, vscmd,
cmSystemTools::KeyWOW64_32)) {
cmSystemTools::ConvertToUnixSlashes(vscmd);
vscmd += "/Common7/IDE/devenv.com";
if (cmSystemTools::FileExists(vscmd, true)) {
return vscmd;
}
}
vscmd = "devenv.com";
return vscmd;
}
char const* cmGlobalVisualStudio7Generator::ExternalProjectType(
std::string const& location)
{
std::string extension = cmSystemTools::GetFilenameLastExtension(location);
if (extension == ".vbproj"_s) {
return "F184B08F-C81C-45F6-A57F-5ABD9991F28F";
}
if (extension == ".csproj"_s) {
return "FAE04EC0-301F-11D3-BF4B-00C04F79EFBC";
}
if (extension == ".fsproj"_s) {
return "F2A71F9B-5D33-465A-A702-920D77279786";
}
if (extension == ".vdproj"_s) {
return "54435603-DBB4-11D2-8724-00A0C9A8B90C";
}
if (extension == ".dbproj"_s) {
return "C8D11400-126E-41CD-887F-60BD40844F9E";
}
if (extension == ".wixproj"_s) {
return "930C7802-8A8C-48F9-8165-68863BCCD9DD";
}
if (extension == ".pyproj"_s) {
return "888888A0-9F3D-457C-B088-3A5042F75D52";
}
return "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942";
}
std::vector<cmGlobalGenerator::GeneratedMakeCommand>
cmGlobalVisualStudio7Generator::GenerateBuildCommand(
std::string const& makeProgram, std::string const& projectName,
std::string const& projectDir, std::vector<std::string> const& targetNames,
std::string const& config, int /*jobs*/, bool /*verbose*/,
cmBuildOptions /*buildOptions*/, std::vector<std::string> const& makeOptions)
{
// Select the caller- or user-preferred make program, else devenv.
std::string makeProgramSelected =
this->SelectMakeProgram(makeProgram, this->GetDevEnvCommand());
std::string const slnFile = this->GetSLNFile(projectDir, projectName);
// Ignore the above preference if it is msbuild.
// Assume any other value is either a devenv or
// command-line compatible with devenv.
std::string makeProgramLower = makeProgramSelected;
cmSystemTools::LowerCase(makeProgramLower);
if (makeProgramLower.find("msbuild") != std::string::npos) {
makeProgramSelected = this->GetDevEnvCommand();
}
// Workaround to convince VCExpress.exe to produce output.
bool const requiresOutputForward =
(makeProgramLower.find("vcexpress") != std::string::npos);
std::vector<GeneratedMakeCommand> makeCommands;
std::vector<std::string> realTargetNames = targetNames;
if (targetNames.empty() ||
((targetNames.size() == 1) && targetNames.front().empty())) {
realTargetNames = { "ALL_BUILD" };
}
for (auto const& tname : realTargetNames) {
std::string realTarget;
if (!tname.empty()) {
realTarget = tname;
} else {
continue;
}
bool clean = false;
if (realTarget == "clean"_s) {
clean = true;
realTarget = "ALL_BUILD";
}
GeneratedMakeCommand makeCommand;
makeCommand.RequiresOutputForward = requiresOutputForward;
makeCommand.Add(makeProgramSelected);
makeCommand.Add(slnFile);
makeCommand.Add((clean ? "/clean" : "/build"));
makeCommand.Add((config.empty() ? "Debug" : config));
makeCommand.Add("/project");
makeCommand.Add(realTarget);
makeCommand.Add(makeOptions.begin(), makeOptions.end());
makeCommands.emplace_back(std::move(makeCommand));
}
return makeCommands;
}
//! Create a local generator appropriate to this Global Generator
std::unique_ptr<cmLocalGenerator>
cmGlobalVisualStudio7Generator::CreateLocalGenerator(cmMakefile* mf)
{
auto lg = cm::make_unique<cmLocalVisualStudio7Generator>(this, mf);
return std::unique_ptr<cmLocalGenerator>(std::move(lg));
}
#if !defined(CMAKE_BOOTSTRAP)
Json::Value cmGlobalVisualStudio7Generator::GetJson() const
{
Json::Value generator = this->cmGlobalVisualStudioGenerator::GetJson();
generator["platform"] = this->GetPlatformName();
return generator;
}
#endif
bool cmGlobalVisualStudio7Generator::SetSystemName(std::string const& s,
cmMakefile* mf)
{
mf->AddDefinition("CMAKE_VS_INTEL_Fortran_PROJECT_VERSION",
this->GetIntelProjectVersion());
return this->cmGlobalVisualStudioGenerator::SetSystemName(s, mf);
}
void cmGlobalVisualStudio7Generator::AppendDirectoryForConfig(
std::string const& prefix, std::string const& config,
std::string const& suffix, std::string& dir)
{
if (!config.empty()) {
dir += cmStrCat(prefix, config, suffix);
}
}
std::string cmGlobalVisualStudio7Generator::Encoding()
{
return "UTF-8";
}