a608467180
This method previously required the global generator to be passed, but that was left from before cmTarget had its Makefile member. Now the global generator can be retrieved automatically, so we can drop the method argument.
1018 lines
33 KiB
C++
1018 lines
33 KiB
C++
/*=========================================================================
|
||
|
||
Program: CMake - Cross-Platform Makefile Generator
|
||
Module: $RCSfile$
|
||
Language: C++
|
||
Date: $Date$
|
||
Version: $Revision$
|
||
|
||
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||
|
||
This software is distributed WITHOUT ANY WARRANTY; without even
|
||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||
PURPOSE. See the above copyright notices for more information.
|
||
|
||
=========================================================================*/
|
||
#include "cmVisualStudio10TargetGenerator.h"
|
||
#include "cmGlobalVisualStudio7Generator.h"
|
||
#include "cmTarget.h"
|
||
#include "cmComputeLinkInformation.h"
|
||
#include "cmGeneratedFileStream.h"
|
||
#include "cmMakefile.h"
|
||
#include "cmSourceFile.h"
|
||
#include "cmVisualStudioGeneratorOptions.h"
|
||
#include "cmLocalVisualStudio7Generator.h"
|
||
|
||
#include "cmVS10CLFlagTable.h"
|
||
#include "cmVS10LinkFlagTable.h"
|
||
#include "cmVS10LibFlagTable.h"
|
||
|
||
|
||
|
||
cmVisualStudio10TargetGenerator::
|
||
cmVisualStudio10TargetGenerator(cmTarget* target,
|
||
cmGlobalVisualStudio7Generator* gg)
|
||
{
|
||
this->GlobalGenerator = gg;
|
||
this->GlobalGenerator->CreateGUID(target->GetName());
|
||
this->GUID = this->GlobalGenerator->GetGUID(target->GetName());
|
||
this->Target = target;
|
||
this->Makefile = target->GetMakefile();
|
||
this->LocalGenerator =
|
||
(cmLocalVisualStudio7Generator*)
|
||
this->Makefile->GetLocalGenerator();
|
||
this->Platform = "|Win32";
|
||
}
|
||
|
||
cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator()
|
||
{
|
||
delete this->BuildFileStream;
|
||
}
|
||
|
||
void cmVisualStudio10TargetGenerator::WritePlatformConfigTag(
|
||
const char* tag,
|
||
const char* config,
|
||
int indentLevel,
|
||
const char* attribute,
|
||
const char* end,
|
||
std::ostream* stream)
|
||
|
||
{
|
||
if(!stream)
|
||
{
|
||
stream = this->BuildFileStream;
|
||
}
|
||
stream->fill(' ');
|
||
stream->width(indentLevel*2 );
|
||
(*stream ) << "";
|
||
(*stream ) << "<" << tag
|
||
<< " Condition=\"'$(Configuration)|$(Platform)'=='";
|
||
(*stream ) << config << this->Platform << "'\"";
|
||
if(attribute)
|
||
{
|
||
(*stream ) << attribute;
|
||
}
|
||
// close the tag
|
||
(*stream ) << ">";
|
||
if(end)
|
||
{
|
||
(*stream ) << end;
|
||
}
|
||
}
|
||
|
||
void cmVisualStudio10TargetGenerator::WriteString(const char* line,
|
||
int indentLevel)
|
||
{
|
||
this->BuildFileStream->fill(' ');
|
||
this->BuildFileStream->width(indentLevel*2 );
|
||
// write an empty string to get the fill level indent to print
|
||
(*this->BuildFileStream ) << "";
|
||
(*this->BuildFileStream ) << line;
|
||
}
|
||
|
||
void cmVisualStudio10TargetGenerator::Generate()
|
||
{
|
||
// Tell the global generator the name of the project file
|
||
this->Target->SetProperty("GENERATOR_FILE_NAME",this->Target->GetName());
|
||
this->Target->SetProperty("GENERATOR_FILE_NAME_EXT",
|
||
".vcxproj");
|
||
cmMakefile* mf = this->Target->GetMakefile();
|
||
std::string path = mf->GetStartOutputDirectory();
|
||
path += "/";
|
||
path += this->Target->GetName();
|
||
path += ".vcxproj";
|
||
this->BuildFileStream =
|
||
new cmGeneratedFileStream(path.c_str());
|
||
this->BuildFileStream->SetCopyIfDifferent(true);
|
||
|
||
// Write the encoding header into the file
|
||
char magic[] = {0xEF,0xBB, 0xBF};
|
||
this->BuildFileStream->write(magic, 3);
|
||
this->WriteString("<Project DefaultTargets=\"Build\" "
|
||
"ToolsVersion=\"4.0\" "
|
||
"xmlns=\"http://schemas.microsoft.com/"
|
||
"developer/msbuild/2003\">\n",
|
||
0);
|
||
this->WriteProjectConfigurations();
|
||
this->WriteString("<PropertyGroup Label=\"Globals\">\n", 1);
|
||
this->WriteString("<ProjectGUID>", 2);
|
||
(*this->BuildFileStream) << "{" << this->GUID << "}</ProjectGUID>\n";
|
||
|
||
this->WriteString("<SccProjectName />\n", 2);
|
||
this->WriteString("<SccLocalPath />\n", 2);
|
||
this->WriteString("<Keyword>Win32Proj</Keyword>\n", 2);
|
||
this->WriteString("</PropertyGroup>\n", 1);
|
||
this->WriteString("<Import Project="
|
||
"\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n",
|
||
1);
|
||
this->WriteProjectConfigurationValues();
|
||
this->WriteString(
|
||
"<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n", 1);
|
||
this->WriteString("<ImportGroup Label=\"ExtensionSettings\">\n", 1);
|
||
this->WriteString("</ImportGroup>\n", 1);
|
||
this->WriteString("<ImportGroup Label=\"PropertySheets\">\n", 1);
|
||
this->WriteString("<Import Project="
|
||
"\"$(LocalAppData)\\Microsoft\\VisualStudio\\10.0\\"
|
||
"Microsoft.Cpp.$(Platform).user.props\" "
|
||
"Condition=\"exists('$(LocalAppData)\\Microsoft"
|
||
"\\VisualStudio\\10.0\\"
|
||
"Microsoft.Cpp.$(Platform).user.props')\" />\n", 2);
|
||
this->WriteString("</ImportGroup>\n", 1);
|
||
this->WriteString("<PropertyGroup Label=\"UserMacros\" />\n", 1);
|
||
this->WritePathAndIncrementalLinkOptions();
|
||
this->WriteItemDefinitionGroups();
|
||
this->WriteCustomCommands();
|
||
this->WriteObjSources();
|
||
this->WriteCLSources();
|
||
this->WriteProjectReferences();
|
||
this->WriteString(
|
||
"<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\""
|
||
" />\n", 1);
|
||
this->WriteString("<ImportGroup Label=\"ExtensionTargets\">\n", 1);
|
||
this->WriteString("</ImportGroup>\n", 1);
|
||
this->WriteString("</Project>", 0);
|
||
// The groups are stored in a separate file for VS 10
|
||
this->WriteGroups();
|
||
}
|
||
|
||
// ConfigurationType Application, Utility StaticLibrary DynamicLibrary
|
||
|
||
void cmVisualStudio10TargetGenerator::WriteProjectConfigurations()
|
||
{
|
||
this->WriteString("<ItemGroup Label=\"ProjectConfigurations\">\n", 1);
|
||
std::vector<std::string> *configs =
|
||
static_cast<cmGlobalVisualStudio7Generator *>
|
||
(this->GlobalGenerator)->GetConfigurations();
|
||
for(std::vector<std::string>::iterator i = configs->begin();
|
||
i != configs->end(); ++i)
|
||
{
|
||
this->WriteString("<ProjectConfiguration Include=\"", 2);
|
||
(*this->BuildFileStream ) << *i << this->Platform << "\">\n";
|
||
this->WriteString("<Configuration>", 3);
|
||
(*this->BuildFileStream ) << *i << "</Configuration>\n";
|
||
this->WriteString("<Platform>Win32</Platform>\n", 3);
|
||
this->WriteString("</ProjectConfiguration>\n", 2);
|
||
}
|
||
this->WriteString("</ItemGroup>\n", 1);
|
||
}
|
||
|
||
void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
|
||
{
|
||
std::vector<std::string> *configs =
|
||
static_cast<cmGlobalVisualStudio7Generator *>
|
||
(this->GlobalGenerator)->GetConfigurations();
|
||
for(std::vector<std::string>::iterator i = configs->begin();
|
||
i != configs->end(); ++i)
|
||
{
|
||
this->WritePlatformConfigTag("PropertyGroup",
|
||
i->c_str(),
|
||
1, " Label=\"Configuration\"", "\n");
|
||
std::string configType = "<ConfigurationType>";
|
||
switch(this->Target->GetType())
|
||
{
|
||
case cmTarget::SHARED_LIBRARY:
|
||
case cmTarget::MODULE_LIBRARY:
|
||
configType += "DynamicLibrary";
|
||
break;
|
||
case cmTarget::STATIC_LIBRARY:
|
||
configType += "StaticLibrary";
|
||
break;
|
||
case cmTarget::EXECUTABLE:
|
||
configType += "Application";
|
||
break;
|
||
case cmTarget::UTILITY:
|
||
configType += "Utility";
|
||
break;
|
||
}
|
||
configType += "</ConfigurationType>\n";
|
||
this->WriteString(configType.c_str(), 2);
|
||
const char* mfcFlag =
|
||
this->Target->GetMakefile()->GetDefinition("CMAKE_MFC_FLAG");
|
||
if(mfcFlag)
|
||
{
|
||
this->WriteString("<UseOfMfc>true</UseOfMfc>\n", 2);
|
||
}
|
||
else
|
||
{
|
||
this->WriteString("<UseOfMfc>false</UseOfMfc>\n", 2);
|
||
}
|
||
this->WriteString("<CharacterSet>MultiByte</CharacterSet>\n", 2);
|
||
this->WriteString("</PropertyGroup>\n", 1);
|
||
}
|
||
}
|
||
|
||
void cmVisualStudio10TargetGenerator::WriteCustomCommands()
|
||
{
|
||
this->WriteString("<ItemGroup>\n", 1);
|
||
std::vector<cmSourceFile*>const & sources = this->Target->GetSourceFiles();
|
||
for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
|
||
source != sources.end(); ++source)
|
||
{
|
||
if(cmCustomCommand const* command = (*source)->GetCustomCommand())
|
||
{
|
||
this->WriteCustomRule(*source, *command);
|
||
}
|
||
}
|
||
this->WriteString("</ItemGroup>\n", 1);
|
||
}
|
||
|
||
void
|
||
cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source,
|
||
cmCustomCommand const &
|
||
command)
|
||
{
|
||
std::string sourcePath = source->GetFullPath();
|
||
// the rule file seems to need to exist for vs10
|
||
if (source->GetExtension() == "rule")
|
||
{
|
||
if(!cmSystemTools::FileExists(sourcePath.c_str()))
|
||
{
|
||
std::ofstream fout(sourcePath.c_str());
|
||
if(fout)
|
||
{
|
||
fout << "# generated from CMake\n";
|
||
fout.flush();
|
||
fout.close();
|
||
}
|
||
}
|
||
}
|
||
cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
|
||
std::string comment = lg->ConstructComment(command);
|
||
std::vector<std::string> *configs =
|
||
static_cast<cmGlobalVisualStudio7Generator *>
|
||
(this->GlobalGenerator)->GetConfigurations();
|
||
this->WriteString("<CustomBuild Include=\"", 2);
|
||
(*this->BuildFileStream ) <<
|
||
cmSystemTools::RelativePath(this->Makefile->GetCurrentOutputDirectory(),
|
||
sourcePath.c_str()) << "\">\n";
|
||
for(std::vector<std::string>::iterator i = configs->begin();
|
||
i != configs->end(); ++i)
|
||
{
|
||
std::string script =
|
||
lg->ConstructScript(command.GetCommandLines(),
|
||
command.GetWorkingDirectory(),
|
||
i->c_str(),
|
||
command.GetEscapeOldStyle(),
|
||
command.GetEscapeAllowMakeVars());
|
||
this->WritePlatformConfigTag("Message",i->c_str(), 3);
|
||
(*this->BuildFileStream ) << comment << "</Message>\n";
|
||
this->WritePlatformConfigTag("Command", i->c_str(), 3);
|
||
(*this->BuildFileStream ) << script << "</Command>\n";
|
||
this->WritePlatformConfigTag("AdditionalInputs", i->c_str(), 3);
|
||
|
||
(*this->BuildFileStream ) << source->GetFullPath();
|
||
for(std::vector<std::string>::const_iterator d =
|
||
command.GetDepends().begin();
|
||
d != command.GetDepends().end();
|
||
++d)
|
||
{
|
||
std::string dep = this->LocalGenerator->
|
||
GetRealDependency(d->c_str(), i->c_str());
|
||
this->ConvertToWindowsSlash(dep);
|
||
(*this->BuildFileStream ) << ";" << dep;
|
||
}
|
||
(*this->BuildFileStream ) << ";%(AdditionalInputs)</AdditionalInputs>\n";
|
||
this->WritePlatformConfigTag("Outputs", i->c_str(), 3);
|
||
const char* sep = "";
|
||
for(std::vector<std::string>::const_iterator o =
|
||
command.GetOutputs().begin();
|
||
o != command.GetOutputs().end();
|
||
++o)
|
||
{
|
||
std::string out = *o;
|
||
this->ConvertToWindowsSlash(out);
|
||
(*this->BuildFileStream ) << sep << out;
|
||
sep = ";";
|
||
}
|
||
(*this->BuildFileStream ) << ";%(Outputs)</Outputs>\n";
|
||
}
|
||
this->WriteString("</CustomBuild>\n", 2);
|
||
}
|
||
|
||
void cmVisualStudio10TargetGenerator::ConvertToWindowsSlash(std::string& s)
|
||
{
|
||
// first convert all of the slashes
|
||
std::string::size_type pos = 0;
|
||
while((pos = s.find('/', pos)) != std::string::npos)
|
||
{
|
||
s[pos] = '\\';
|
||
pos++;
|
||
}
|
||
}
|
||
void cmVisualStudio10TargetGenerator::WriteGroups()
|
||
{
|
||
// This should create a target.vcxproj.filters file
|
||
// something like this:
|
||
|
||
/*
|
||
<?xml version="1.0" encoding="utf-8"?>
|
||
<Project ToolsVersion="4.0"
|
||
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||
<ItemGroup>
|
||
<CustomBuild Include="..\CMakeLists.txt" />
|
||
</ItemGroup>
|
||
<ItemGroup>
|
||
<Filter Include="Source Files">
|
||
<UniqueIdentifier>{05072589-c7be-439a-8fd7-5db6ee5008a9}
|
||
</UniqueIdentifier>
|
||
</Filter>
|
||
</ItemGroup>
|
||
<ItemGroup>
|
||
<ClCompile Include="..\foo.c">
|
||
<Filter>Source Files</Filter>
|
||
</ClCompile>
|
||
<ClCompile Include="..\testCCompiler.c">
|
||
<Filter>Source Files</Filter>
|
||
</ClCompile>
|
||
</ItemGroup>
|
||
</Project>
|
||
*/
|
||
}
|
||
|
||
|
||
void cmVisualStudio10TargetGenerator::WriteObjSources()
|
||
{
|
||
if(this->Target->GetType() > cmTarget::MODULE_LIBRARY)
|
||
{
|
||
return;
|
||
}
|
||
bool first = true;
|
||
std::vector<cmSourceFile*>const & sources = this->Target->GetSourceFiles();
|
||
for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
|
||
source != sources.end(); ++source)
|
||
{
|
||
if((*source)->GetExtension() == "obj")
|
||
{
|
||
if(first)
|
||
{
|
||
this->WriteString("<ItemGroup>\n", 1);
|
||
first = false;
|
||
}
|
||
this->WriteString("<None Include=\"", 2);
|
||
(*this->BuildFileStream ) << (*source)->GetFullPath() << "\" />\n";
|
||
}
|
||
}
|
||
if(!first)
|
||
{
|
||
this->WriteString("</ItemGroup>\n", 1);
|
||
}
|
||
}
|
||
|
||
|
||
void cmVisualStudio10TargetGenerator::WriteCLSources()
|
||
{
|
||
this->WriteString("<ItemGroup>\n", 1);
|
||
if(this->Target->GetType() > cmTarget::MODULE_LIBRARY)
|
||
{
|
||
this->WriteString("<None Include=\"", 2);
|
||
(*this->BuildFileStream ) << this->Target->GetDirectory()
|
||
<< "\\" << this->Target->GetName()
|
||
<< "\" />\n";
|
||
}
|
||
else
|
||
{
|
||
std::vector<cmSourceFile*>const& sources = this->Target->GetSourceFiles();
|
||
for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
|
||
source != sources.end(); ++source)
|
||
{
|
||
// if it is not a custom command then add it as a c/c++ file,
|
||
// TODO: need to check for idl or rc
|
||
if(!(*source)->GetCustomCommand()
|
||
&& !(*source)->GetPropertyAsBool("HEADER_FILE_ONLY")
|
||
&& !this->GlobalGenerator->IgnoreFile
|
||
((*source)->GetExtension().c_str()))
|
||
{
|
||
const char* lang = (*source)->GetLanguage();
|
||
if(lang && (strcmp(lang, "C") == 0 || strcmp(lang, "CXX") ==0))
|
||
{
|
||
std::string sourceFile = (*source)->GetFullPath();
|
||
// output the source file
|
||
this->WriteString("<ClCompile Include=\"", 2);
|
||
(*this->BuildFileStream ) << sourceFile << "\"";
|
||
// ouput any flags specific to this source file
|
||
if(this->OutputSourceSpecificFlags(*source))
|
||
{
|
||
// if the source file has specific flags the tag
|
||
// is ended on a new line
|
||
this->WriteString("</ClCompile>\n", 2);
|
||
}
|
||
else
|
||
{
|
||
(*this->BuildFileStream ) << " />\n";
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
this->WriteString("</ItemGroup>\n", 1);
|
||
}
|
||
|
||
bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
|
||
cmSourceFile* source)
|
||
{
|
||
cmSourceFile& sf = *source;
|
||
std::string flags;
|
||
std::string defines;
|
||
if(const char* cflags = sf.GetProperty("COMPILE_FLAGS"))
|
||
{
|
||
flags += cflags;
|
||
}
|
||
if(const char* cdefs = sf.GetProperty("COMPILE_DEFINITIONS"))
|
||
{
|
||
defines += cdefs;
|
||
}
|
||
const char* lang =
|
||
this->GlobalGenerator->GetLanguageFromExtension
|
||
(sf.GetExtension().c_str());
|
||
const char* sourceLang = this->LocalGenerator->GetSourceFileLanguage(sf);
|
||
const char* linkLanguage = this->Target->GetLinkerLanguage();
|
||
bool needForceLang = false;
|
||
// source file does not match its extension language
|
||
if(lang && sourceLang && strcmp(lang, sourceLang) != 0)
|
||
{
|
||
needForceLang = true;
|
||
lang = sourceLang;
|
||
}
|
||
// if the source file does not match the linker language
|
||
// then force c or c++
|
||
if(needForceLang || (linkLanguage && lang
|
||
&& strcmp(lang, linkLanguage) != 0))
|
||
{
|
||
if(strcmp(lang, "CXX") == 0)
|
||
{
|
||
// force a C++ file type
|
||
flags += " /TP ";
|
||
}
|
||
else if(strcmp(lang, "C") == 0)
|
||
{
|
||
// force to c
|
||
flags += " /TC ";
|
||
}
|
||
}
|
||
// for the first time we need a new line if there is something
|
||
// produced here.
|
||
const char* firstString = ">\n";
|
||
std::vector<std::string> *configs =
|
||
static_cast<cmGlobalVisualStudio7Generator *>
|
||
(this->GlobalGenerator)->GetConfigurations();
|
||
bool hasFlags = false;
|
||
for( std::vector<std::string>::iterator config = configs->begin();
|
||
config != configs->end(); ++config)
|
||
{
|
||
std::string configUpper = cmSystemTools::UpperCase(*config);
|
||
std::string configDefines = defines;
|
||
std::string defPropName = "COMPILE_DEFINITIONS_";
|
||
defPropName += configUpper;
|
||
if(const char* ccdefs = sf.GetProperty(defPropName.c_str()))
|
||
{
|
||
if(configDefines.size())
|
||
{
|
||
configDefines += ",";
|
||
}
|
||
configDefines += ccdefs;
|
||
}
|
||
// if we have flags or defines for this config then
|
||
// use them
|
||
if(flags.size() || configDefines.size())
|
||
{
|
||
(*this->BuildFileStream ) << firstString;
|
||
firstString = ""; // only do firstString once
|
||
hasFlags = true;
|
||
cmVisualStudioGeneratorOptions
|
||
clOptions(this->LocalGenerator,
|
||
10, cmVisualStudioGeneratorOptions::Compiler,
|
||
cmVS10CLFlagTable, 0, this);
|
||
clOptions.Parse(flags.c_str());
|
||
clOptions.AddDefines(configDefines.c_str());
|
||
clOptions.SetConfiguration((*config).c_str());
|
||
clOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", "");
|
||
clOptions.OutputFlagMap(*this->BuildFileStream, " ");
|
||
clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream,
|
||
" ", "\n");
|
||
|
||
}
|
||
}
|
||
return hasFlags;
|
||
}
|
||
|
||
|
||
void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions()
|
||
{
|
||
this->WriteString("<PropertyGroup>\n", 2);
|
||
this->WriteString("<_ProjectFileVersion>10.0.20506.1"
|
||
"</_ProjectFileVersion>\n", 3);
|
||
std::vector<std::string> *configs =
|
||
static_cast<cmGlobalVisualStudio7Generator *>
|
||
(this->GlobalGenerator)->GetConfigurations();
|
||
for(std::vector<std::string>::iterator config = configs->begin();
|
||
config != configs->end(); ++config)
|
||
{
|
||
std::string targetNameFull =
|
||
this->Target->GetFullName(config->c_str());
|
||
std::string intermediateDir = this->LocalGenerator->
|
||
GetTargetDirectory(*this->Target);
|
||
intermediateDir += "/";
|
||
intermediateDir += *config;
|
||
intermediateDir += "/";
|
||
this->ConvertToWindowsSlash(intermediateDir);
|
||
std::string outDir = this->Target->GetDirectory(config->c_str());
|
||
this->ConvertToWindowsSlash(outDir);
|
||
this->WritePlatformConfigTag("OutDir", config->c_str(), 3);
|
||
*this->BuildFileStream << outDir
|
||
<< "\\"
|
||
<< "</OutDir>\n";
|
||
this->WritePlatformConfigTag("IntDir", config->c_str(), 3);
|
||
*this->BuildFileStream << intermediateDir
|
||
<< "</IntDir>\n";
|
||
this->WritePlatformConfigTag("TargetName", config->c_str(), 3);
|
||
*this->BuildFileStream << cmSystemTools::GetFilenameWithoutExtension(
|
||
targetNameFull.c_str())
|
||
<< "</TargetName>\n";
|
||
|
||
this->WritePlatformConfigTag("TargetExt", config->c_str(), 3);
|
||
*this->BuildFileStream << cmSystemTools::GetFilenameLastExtension(
|
||
targetNameFull.c_str())
|
||
<< "</TargetExt>\n";
|
||
this->OutputLinkIncremental(*config);
|
||
}
|
||
this->WriteString("</PropertyGroup>\n", 2);
|
||
|
||
}
|
||
|
||
|
||
|
||
void
|
||
cmVisualStudio10TargetGenerator::
|
||
OutputLinkIncremental(std::string const& configName)
|
||
{
|
||
std::string CONFIG = cmSystemTools::UpperCase(configName);
|
||
// static libraries and things greater than modules do not need
|
||
// to set this option
|
||
if(this->Target->GetType() == cmTarget::STATIC_LIBRARY
|
||
|| this->Target->GetType() > cmTarget::MODULE_LIBRARY)
|
||
{
|
||
return;
|
||
}
|
||
const char* linkType = "SHARED";
|
||
if(this->Target->GetType() == cmTarget::EXECUTABLE)
|
||
{
|
||
linkType = "EXE";
|
||
}
|
||
|
||
// assume incremental linking
|
||
const char* incremental = "true";
|
||
const char* linkLanguage = this->Target->GetLinkerLanguage();
|
||
if(!linkLanguage)
|
||
{
|
||
cmSystemTools::Error
|
||
("CMake can not determine linker language for target:",
|
||
this->Target->GetName());
|
||
return;
|
||
}
|
||
std::string linkFlagVarBase = "CMAKE_";
|
||
linkFlagVarBase += linkType;
|
||
linkFlagVarBase += "_LINKER_FLAGS";
|
||
std::string flags = this->
|
||
Target->GetMakefile()->GetRequiredDefinition(linkFlagVarBase.c_str());
|
||
std::string linkFlagVar = linkFlagVarBase + "_" + CONFIG;
|
||
flags += this->
|
||
Target->GetMakefile()->GetRequiredDefinition(linkFlagVar.c_str());
|
||
if(strcmp(linkLanguage, "C") == 0 || strcmp(linkLanguage, "CXX") == 0
|
||
|| strcmp(linkLanguage, "Fortran") == 0)
|
||
{
|
||
std::string baseFlagVar = "CMAKE_";
|
||
baseFlagVar += linkLanguage;
|
||
baseFlagVar += "_FLAGS";
|
||
flags += this->
|
||
Target->GetMakefile()->GetRequiredDefinition(baseFlagVar.c_str());
|
||
std::string flagVar = baseFlagVar + std::string("_") + CONFIG;
|
||
flags +=
|
||
Target->GetMakefile()->GetRequiredDefinition(flagVar.c_str());
|
||
}
|
||
if(flags.find("INCREMENTAL:NO") != flags.npos)
|
||
{
|
||
incremental = "false";
|
||
}
|
||
this->WritePlatformConfigTag("LinkIncremental", configName.c_str(), 3);
|
||
*this->BuildFileStream << incremental
|
||
<< "</LinkIncremental>\n";
|
||
}
|
||
|
||
|
||
void
|
||
cmVisualStudio10TargetGenerator::
|
||
WriteClOptions(std::string const& configName,
|
||
std::vector<std::string> const & includes)
|
||
{
|
||
|
||
// much of this was copied from here:
|
||
// copied from cmLocalVisualStudio7Generator.cxx 805
|
||
|
||
this->WriteString("<ClCompile>\n", 2);
|
||
cmVisualStudioGeneratorOptions
|
||
clOptions(this->LocalGenerator,
|
||
10, cmVisualStudioGeneratorOptions::Compiler,
|
||
cmVS10CLFlagTable);
|
||
std::string flags;
|
||
// collect up flags for
|
||
if(this->Target->GetType() < cmTarget::UTILITY)
|
||
{
|
||
const char* linkLanguage = this->Target->GetLinkerLanguage();
|
||
if(!linkLanguage)
|
||
{
|
||
cmSystemTools::Error
|
||
("CMake can not determine linker language for target:",
|
||
this->Target->GetName());
|
||
return;
|
||
}
|
||
if(strcmp(linkLanguage, "C") == 0 || strcmp(linkLanguage, "CXX") == 0
|
||
|| strcmp(linkLanguage, "Fortran") == 0)
|
||
{
|
||
std::string baseFlagVar = "CMAKE_";
|
||
baseFlagVar += linkLanguage;
|
||
baseFlagVar += "_FLAGS";
|
||
flags = this->
|
||
Target->GetMakefile()->GetRequiredDefinition(baseFlagVar.c_str());
|
||
std::string flagVar = baseFlagVar + std::string("_") +
|
||
cmSystemTools::UpperCase(configName);
|
||
flags += " ";
|
||
flags += this->
|
||
Target->GetMakefile()->GetRequiredDefinition(flagVar.c_str());
|
||
}
|
||
// set the correct language
|
||
if(strcmp(linkLanguage, "C") == 0)
|
||
{
|
||
flags += " /TC ";
|
||
}
|
||
if(strcmp(linkLanguage, "CXX") == 0)
|
||
{
|
||
flags += " /TP ";
|
||
}
|
||
}
|
||
std::string configUpper = cmSystemTools::UpperCase(configName);
|
||
std::string defPropName = "COMPILE_DEFINITIONS_";
|
||
defPropName += configUpper;
|
||
|
||
// Get preprocessor definitions for this directory.
|
||
std::string defineFlags = this->Target->GetMakefile()->GetDefineFlags();
|
||
clOptions.FixExceptionHandlingDefault();
|
||
clOptions.Parse(flags.c_str());
|
||
clOptions.Parse(defineFlags.c_str());
|
||
clOptions.AddDefines
|
||
(this->Makefile->GetProperty("COMPILE_DEFINITIONS"));
|
||
clOptions.AddDefines(this->Target->GetProperty("COMPILE_DEFINITIONS"));
|
||
clOptions.AddDefines(this->Makefile->GetProperty(defPropName.c_str()));
|
||
clOptions.AddDefines(this->Target->GetProperty(defPropName.c_str()));
|
||
clOptions.SetVerboseMakefile(
|
||
this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));
|
||
|
||
// Add a definition for the configuration name.
|
||
std::string configDefine = "CMAKE_INTDIR=\"";
|
||
configDefine += configName;
|
||
configDefine += "\"";
|
||
clOptions.AddDefine(configDefine);
|
||
if(const char* exportMacro = this->Target->GetExportMacro())
|
||
{
|
||
clOptions.AddDefine(exportMacro);
|
||
}
|
||
clOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", "");
|
||
this->OutputIncludes(includes);
|
||
clOptions.OutputFlagMap(*this->BuildFileStream, " ");
|
||
clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
|
||
"\n");
|
||
this->WriteString("<AssemblerListingLocation>", 3);
|
||
*this->BuildFileStream << configName
|
||
<< "</AssemblerListingLocation>\n";
|
||
this->WriteString("<ObjectFileName>$(IntDir)</ObjectFileName>\n", 3);
|
||
this->WriteString("<ProgramDataBaseFileName>", 3);
|
||
*this->BuildFileStream << this->Target->GetDirectory(configName.c_str())
|
||
<< "/"
|
||
<< this->Target->GetPDBName(configName.c_str())
|
||
<< "</ProgramDataBaseFileName>\n";
|
||
this->WriteString("</ClCompile>\n", 2);
|
||
}
|
||
|
||
void cmVisualStudio10TargetGenerator::
|
||
OutputIncludes(std::vector<std::string> const & includes)
|
||
{
|
||
this->WriteString("<AdditionalIncludeDirectories>", 3);
|
||
for(std::vector<std::string>::const_iterator i = includes.begin();
|
||
i != includes.end(); ++i)
|
||
{
|
||
*this->BuildFileStream << *i << ";";
|
||
}
|
||
this->WriteString("%(AdditionalIncludeDirectories)"
|
||
"</AdditionalIncludeDirectories>\n", 0);
|
||
}
|
||
|
||
|
||
|
||
void cmVisualStudio10TargetGenerator::
|
||
WriteRCOptions(std::string const& ,
|
||
std::vector<std::string> const & includes)
|
||
{
|
||
this->WriteString("<ResourceCompile>\n", 2);
|
||
this->OutputIncludes(includes);
|
||
this->WriteString("</ResourceCompile>\n", 2);
|
||
}
|
||
|
||
|
||
void cmVisualStudio10TargetGenerator::WriteLibOptions(std::string const&
|
||
)
|
||
{
|
||
if(this->Target->GetType() != cmTarget::STATIC_LIBRARY)
|
||
{
|
||
return;
|
||
}
|
||
if(const char* libflags = this->Target
|
||
->GetProperty("STATIC_LIBRARY_FLAGS"))
|
||
{
|
||
this->WriteString("<Lib>\n", 2);
|
||
cmVisualStudioGeneratorOptions
|
||
libOptions(this->LocalGenerator,
|
||
10, cmVisualStudioGeneratorOptions::Compiler,
|
||
cmVS10LibFlagTable, 0, this);
|
||
libOptions.Parse(libflags);
|
||
libOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", "");
|
||
libOptions.OutputFlagMap(*this->BuildFileStream, " ");
|
||
this->WriteString("</Lib>\n", 2);
|
||
}
|
||
}
|
||
|
||
|
||
void cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const&
|
||
config)
|
||
{
|
||
|
||
// static libraries and things greater than modules do not need
|
||
// to set this option
|
||
if(this->Target->GetType() == cmTarget::STATIC_LIBRARY
|
||
|| this->Target->GetType() > cmTarget::MODULE_LIBRARY)
|
||
{
|
||
return;
|
||
}
|
||
const char* linkLanguage = this->Target->GetLinkerLanguage();
|
||
if(!linkLanguage)
|
||
{
|
||
cmSystemTools::Error
|
||
("CMake can not determine linker language for target:",
|
||
this->Target->GetName());
|
||
return;
|
||
}
|
||
|
||
this->WriteString("<Link>\n", 2);
|
||
std::string CONFIG = cmSystemTools::UpperCase(config);
|
||
|
||
const char* linkType = "SHARED";
|
||
if(this->Target->GetType() == cmTarget::MODULE_LIBRARY)
|
||
{
|
||
linkType = "MODULE";
|
||
}
|
||
if(this->Target->GetType() == cmTarget::EXECUTABLE)
|
||
{
|
||
linkType = "EXE";
|
||
}
|
||
std::string stackVar = "CMAKE_";
|
||
stackVar += linkLanguage;
|
||
stackVar += "_STACK_SIZE";
|
||
const char* stackVal = this->Makefile->GetDefinition(stackVar.c_str());
|
||
std::string flags;
|
||
if(stackVal)
|
||
{
|
||
flags += " ";
|
||
flags += stackVal;
|
||
}
|
||
// assume incremental linking
|
||
std::string linkFlagVarBase = "CMAKE_";
|
||
linkFlagVarBase += linkType;
|
||
linkFlagVarBase += "_LINKER_FLAGS";
|
||
flags += " ";
|
||
flags += this->
|
||
Target->GetMakefile()->GetRequiredDefinition(linkFlagVarBase.c_str());
|
||
std::string linkFlagVar = linkFlagVarBase + "_" + CONFIG;
|
||
flags += " ";
|
||
flags += this->
|
||
Target->GetMakefile()->GetRequiredDefinition(linkFlagVar.c_str());
|
||
const char* targetLinkFlags = this->Target->GetProperty("LINK_FLAGS");
|
||
if(targetLinkFlags)
|
||
{
|
||
flags += " ";
|
||
flags += targetLinkFlags;
|
||
}
|
||
cmVisualStudioGeneratorOptions
|
||
linkOptions(this->LocalGenerator,
|
||
10, cmVisualStudioGeneratorOptions::Compiler,
|
||
cmVS10LinkFlagTable);
|
||
if ( this->Target->GetPropertyAsBool("WIN32_EXECUTABLE") )
|
||
{
|
||
flags += " /SUBSYSTEM:WINDOWS";
|
||
}
|
||
else
|
||
{
|
||
flags += " /SUBSYSTEM:CONSOLE";
|
||
}
|
||
cmSystemTools::ReplaceString(flags, "/INCREMENTAL:YES", "");
|
||
cmSystemTools::ReplaceString(flags, "/INCREMENTAL:NO", "");
|
||
std::string standardLibsVar = "CMAKE_";
|
||
standardLibsVar += linkLanguage;
|
||
standardLibsVar += "_STANDARD_LIBRARIES";
|
||
std::string
|
||
libs = this->Makefile->GetSafeDefinition(standardLibsVar.c_str());
|
||
// Remove trailing spaces from libs
|
||
std::string::size_type pos = libs.size()-1;
|
||
if(libs.size() != 0)
|
||
{
|
||
while(libs[pos] == ' ')
|
||
{
|
||
pos--;
|
||
}
|
||
}
|
||
if(pos != libs.size()-1)
|
||
{
|
||
libs = libs.substr(0, pos+1);
|
||
}
|
||
// Replace spaces in libs with ;
|
||
cmSystemTools::ReplaceString(libs, " ", ";");
|
||
cmComputeLinkInformation* pcli =
|
||
this->Target->GetLinkInformation(config.c_str());
|
||
if(!pcli)
|
||
{
|
||
cmSystemTools::Error
|
||
("CMake can not compute cmComputeLinkInformation for target:",
|
||
this->Target->GetName());
|
||
return;
|
||
}
|
||
// add the libraries for the target to libs string
|
||
cmComputeLinkInformation& cli = *pcli;
|
||
this->AddLibraries(cli, libs);
|
||
linkOptions.AddFlag("AdditionalDependencies", libs.c_str());
|
||
|
||
std::vector<std::string> const& ldirs = cli.GetDirectories();
|
||
const char* sep = "";
|
||
std::string linkDirs;
|
||
for(std::vector<std::string>::const_iterator d = ldirs.begin();
|
||
d != ldirs.end(); ++d)
|
||
{
|
||
linkDirs += sep;
|
||
linkDirs += *d;
|
||
sep = ";";
|
||
}
|
||
linkDirs += "%(AdditionalLibraryDirectories)";
|
||
linkOptions.AddFlag("AdditionalLibraryDirectories", linkDirs.c_str());
|
||
linkOptions.AddFlag("AdditionalDependencies", libs.c_str());
|
||
linkOptions.AddFlag("Version", "0.0");
|
||
if(linkOptions.IsDebug() || flags.find("/debug") != flags.npos)
|
||
{
|
||
linkOptions.AddFlag("GenerateDebugInformation", "true");
|
||
}
|
||
else
|
||
{
|
||
linkOptions.AddFlag("GenerateDebugInformation", "false");
|
||
}
|
||
std::string targetName;
|
||
std::string targetNameSO;
|
||
std::string targetNameFull;
|
||
std::string targetNameImport;
|
||
std::string targetNamePDB;
|
||
if(this->Target->GetType() == cmTarget::EXECUTABLE)
|
||
{
|
||
this->Target->GetExecutableNames(targetName, targetNameFull,
|
||
targetNameImport, targetNamePDB,
|
||
config.c_str());
|
||
}
|
||
else
|
||
{
|
||
this->Target->GetLibraryNames(targetName, targetNameSO, targetNameFull,
|
||
targetNameImport, targetNamePDB,
|
||
config.c_str());
|
||
}
|
||
std::string dir = this->Target->GetDirectory(config.c_str());
|
||
dir += "/";
|
||
std::string imLib = dir;
|
||
imLib += targetNameImport;
|
||
std::string pdb = dir;
|
||
pdb += targetNamePDB;
|
||
linkOptions.AddFlag("ImportLibrary", imLib.c_str());
|
||
linkOptions.AddFlag("ProgramDataBaseFileName", pdb.c_str());
|
||
linkOptions.Parse(flags.c_str());
|
||
linkOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", "");
|
||
linkOptions.OutputFlagMap(*this->BuildFileStream, " ");
|
||
|
||
this->WriteString("</Link>\n", 2);
|
||
}
|
||
|
||
void cmVisualStudio10TargetGenerator::AddLibraries(
|
||
cmComputeLinkInformation& cli,
|
||
std::string& libstring)
|
||
{
|
||
typedef cmComputeLinkInformation::ItemVector ItemVector;
|
||
ItemVector libs = cli.GetItems();
|
||
const char* sep = ";";
|
||
for(ItemVector::const_iterator l = libs.begin(); l != libs.end(); ++l)
|
||
{
|
||
if(l->IsPath)
|
||
{
|
||
std::string path = this->LocalGenerator->
|
||
Convert(l->Value.c_str(),
|
||
cmLocalGenerator::START_OUTPUT,
|
||
cmLocalGenerator::UNCHANGED);
|
||
libstring += sep;
|
||
libstring += path;
|
||
}
|
||
else
|
||
{
|
||
libstring += sep;
|
||
libstring += l->Value;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
void cmVisualStudio10TargetGenerator::
|
||
WriteMidlOptions(std::string const& /*config*/,
|
||
std::vector<std::string> const & includes)
|
||
{
|
||
this->WriteString("<Midl>\n", 2);
|
||
this->OutputIncludes(includes);
|
||
// Need this stuff, but there is an midl.xml file...
|
||
// should we look for .idl language?, and flags?
|
||
/*
|
||
<MkTypLibCompatible>false</MkTypLibCompatible>
|
||
<TargetEnvironment>Win32</TargetEnvironment>
|
||
<GenerateStublessProxies>true</GenerateStublessProxies>
|
||
<TypeLibraryName>%(FileName).tlb</TypeLibraryName>
|
||
<OutputDirectory>$(IntDir)\</OutputDirectory>
|
||
<HeaderFileName>%(FileName).h</HeaderFileName>
|
||
<DllDataFileName>
|
||
</DllDataFileName>
|
||
<InterfaceIdentifierFileName>%(FileName)_i.c
|
||
</InterfaceIdentifierFileName>
|
||
<ProxyFileName>%(FileName)_p.c</ProxyFileName>
|
||
*/
|
||
this->WriteString("</Midl>\n", 2);
|
||
}
|
||
|
||
void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups()
|
||
{
|
||
std::vector<std::string> *configs =
|
||
static_cast<cmGlobalVisualStudio7Generator *>
|
||
(this->GlobalGenerator)->GetConfigurations();
|
||
std::vector<std::string> includes;
|
||
this->LocalGenerator->GetIncludeDirectories(includes);
|
||
for(std::vector<std::string>::iterator i = configs->begin();
|
||
i != configs->end(); ++i)
|
||
{
|
||
this->WritePlatformConfigTag("ItemDefinitionGroup", i->c_str(), 1);
|
||
*this->BuildFileStream << "\n";
|
||
// output cl compile flags <ClCompile></ClCompile>
|
||
if(this->Target->GetType() <= cmTarget::MODULE_LIBRARY)
|
||
{
|
||
this->WriteClOptions(*i, includes);
|
||
// output rc compile flags <ResourceCompile></ResourceCompile>
|
||
this->WriteRCOptions(*i, includes);
|
||
}
|
||
// output midl flags <Midl></Midl>
|
||
this->WriteMidlOptions(*i, includes);
|
||
// output link flags <Link></Link>
|
||
this->WriteLinkOptions(*i);
|
||
// output lib flags <Lib></Lib>
|
||
this->WriteLibOptions(*i);
|
||
this->WriteString("</ItemDefinitionGroup>\n", 1);
|
||
}
|
||
}
|
||
|
||
|
||
void cmVisualStudio10TargetGenerator::WriteProjectReferences()
|
||
{
|
||
// TODO
|
||
// This should have dependent targets listed like this:
|
||
/*
|
||
<ItemGroup>
|
||
<ProjectReference Include="ZERO_CHECK.vcxproj">
|
||
<Project>{2f1e4f3c-0a51-46c3-aaf9-e486599604f2}</Project>
|
||
</ProjectReference>
|
||
</ItemGroup>
|
||
*/
|
||
}
|