Merge topic 'vs10-source-paths'
d931ce9
VS10: Generate relative source paths when possible (#12570)b2e7c7a
VS11: Do not use source path conversion workaround specific to VS 104248132
VS10: Convert paths normally unless forced to relativec2ba6ba
VS10: Simplify vcxproj.filter file generation4f2d9d2
VS10: Refactor custom commands to use WriteSource
This commit is contained in:
commit
28de11291a
|
@ -13,6 +13,7 @@
|
||||||
#include "cmGlobalVisualStudio10Generator.h"
|
#include "cmGlobalVisualStudio10Generator.h"
|
||||||
#include "cmLocalVisualStudio10Generator.h"
|
#include "cmLocalVisualStudio10Generator.h"
|
||||||
#include "cmMakefile.h"
|
#include "cmMakefile.h"
|
||||||
|
#include "cmSourceFile.h"
|
||||||
#include "cmake.h"
|
#include "cmake.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,6 +51,38 @@ cmLocalGenerator *cmGlobalVisualStudio10Generator::CreateLocalGenerator()
|
||||||
return lg;
|
return lg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void cmGlobalVisualStudio10Generator::Generate()
|
||||||
|
{
|
||||||
|
this->LongestSource = LongestSourcePath();
|
||||||
|
this->cmGlobalVisualStudio8Generator::Generate();
|
||||||
|
if(this->LongestSource.Length > 0)
|
||||||
|
{
|
||||||
|
cmMakefile* mf = this->LongestSource.Target->GetMakefile();
|
||||||
|
cmOStringStream e;
|
||||||
|
e <<
|
||||||
|
"The binary and/or source directory paths may be too long to generate "
|
||||||
|
"Visual Studio 10 files for this project. "
|
||||||
|
"Consider choosing shorter directory names to build this project with "
|
||||||
|
"Visual Studio 10. "
|
||||||
|
"A more detailed explanation follows."
|
||||||
|
"\n"
|
||||||
|
"There is a bug in the VS 10 IDE that renders property dialog fields "
|
||||||
|
"blank for files referenced by full path in the project file. "
|
||||||
|
"However, CMake must reference at least one file by full path:\n"
|
||||||
|
" " << this->LongestSource.SourceFile->GetFullPath() << "\n"
|
||||||
|
"This is because some Visual Studio tools would append the relative "
|
||||||
|
"path to the end of the referencing directory path, as in:\n"
|
||||||
|
" " << mf->GetCurrentOutputDirectory() << "/"
|
||||||
|
<< this->LongestSource.SourceRel << "\n"
|
||||||
|
"and then incorrectly complain that the file does not exist because "
|
||||||
|
"the path length is too long for some internal buffer or API. "
|
||||||
|
"To avoid this problem CMake must use a full path for this file "
|
||||||
|
"which then triggers the VS 10 property dialog bug.";
|
||||||
|
mf->IssueMessage(cmake::WARNING, e.str().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void cmGlobalVisualStudio10Generator
|
void cmGlobalVisualStudio10Generator
|
||||||
::GetDocumentation(cmDocumentationEntry& entry) const
|
::GetDocumentation(cmDocumentationEntry& entry) const
|
||||||
|
@ -230,3 +263,18 @@ cmGlobalVisualStudio10Generator
|
||||||
ruleFile += ".rule";
|
ruleFile += ".rule";
|
||||||
return ruleFile;
|
return ruleFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void cmGlobalVisualStudio10Generator::PathTooLong(
|
||||||
|
cmTarget* target, cmSourceFile* sf, std::string const& sfRel)
|
||||||
|
{
|
||||||
|
size_t len = (strlen(target->GetMakefile()->GetCurrentOutputDirectory()) +
|
||||||
|
1 + sfRel.length());
|
||||||
|
if(len > this->LongestSource.Length)
|
||||||
|
{
|
||||||
|
this->LongestSource.Length = len;
|
||||||
|
this->LongestSource.Target = target;
|
||||||
|
this->LongestSource.SourceFile = sf;
|
||||||
|
this->LongestSource.SourceRel = sfRel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -46,6 +46,8 @@ public:
|
||||||
///! create the correct local generator
|
///! create the correct local generator
|
||||||
virtual cmLocalGenerator *CreateLocalGenerator();
|
virtual cmLocalGenerator *CreateLocalGenerator();
|
||||||
|
|
||||||
|
virtual void Generate();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to determine system infomation such as shared library
|
* Try to determine system infomation such as shared library
|
||||||
* extension, pthreads, byte order etc.
|
* extension, pthreads, byte order etc.
|
||||||
|
@ -79,10 +81,22 @@ public:
|
||||||
/** Generate an <output>.rule file path for a given command output. */
|
/** Generate an <output>.rule file path for a given command output. */
|
||||||
virtual std::string GenerateRuleFile(std::string const& output) const;
|
virtual std::string GenerateRuleFile(std::string const& output) const;
|
||||||
|
|
||||||
|
void PathTooLong(cmTarget* target, cmSourceFile* sf,
|
||||||
|
std::string const& sfRel);
|
||||||
protected:
|
protected:
|
||||||
virtual const char* GetIDEVersion() { return "10.0"; }
|
virtual const char* GetIDEVersion() { return "10.0"; }
|
||||||
|
|
||||||
std::string PlatformToolset;
|
std::string PlatformToolset;
|
||||||
bool ExpressEdition;
|
bool ExpressEdition;
|
||||||
|
private:
|
||||||
|
struct LongestSourcePath
|
||||||
|
{
|
||||||
|
LongestSourcePath(): Length(0), Target(0), SourceFile(0) {}
|
||||||
|
size_t Length;
|
||||||
|
cmTarget* Target;
|
||||||
|
cmSourceFile* SourceFile;
|
||||||
|
std::string SourceRel;
|
||||||
|
};
|
||||||
|
LongestSourcePath LongestSource;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -491,14 +491,9 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source,
|
||||||
std::vector<std::string> *configs =
|
std::vector<std::string> *configs =
|
||||||
static_cast<cmGlobalVisualStudio7Generator *>
|
static_cast<cmGlobalVisualStudio7Generator *>
|
||||||
(this->GlobalGenerator)->GetConfigurations();
|
(this->GlobalGenerator)->GetConfigurations();
|
||||||
this->WriteString("<CustomBuild Include=\"", 2);
|
|
||||||
// custom command have to use relative paths or they do not
|
this->WriteSource("CustomBuild", source, ">\n");
|
||||||
// show up in the GUI
|
|
||||||
std::string path = cmSystemTools::RelativePath(
|
|
||||||
this->Makefile->GetCurrentOutputDirectory(),
|
|
||||||
sourcePath.c_str());
|
|
||||||
this->ConvertToWindowsSlash(path);
|
|
||||||
(*this->BuildFileStream ) << path << "\">\n";
|
|
||||||
for(std::vector<std::string>::iterator i = configs->begin();
|
for(std::vector<std::string>::iterator i = configs->begin();
|
||||||
i != configs->end(); ++i)
|
i != configs->end(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -541,6 +536,18 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source,
|
||||||
this->WriteString("</CustomBuild>\n", 2);
|
this->WriteString("</CustomBuild>\n", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
cmVisualStudio10TargetGenerator::ConvertPath(std::string const& path,
|
||||||
|
bool forceRelative)
|
||||||
|
{
|
||||||
|
return forceRelative
|
||||||
|
? cmSystemTools::RelativePath(
|
||||||
|
this->Makefile->GetCurrentOutputDirectory(), path.c_str())
|
||||||
|
: this->LocalGenerator->Convert(path.c_str(),
|
||||||
|
cmLocalGenerator::START_OUTPUT,
|
||||||
|
cmLocalGenerator::UNCHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
void cmVisualStudio10TargetGenerator::ConvertToWindowsSlash(std::string& s)
|
void cmVisualStudio10TargetGenerator::ConvertToWindowsSlash(std::string& s)
|
||||||
{
|
{
|
||||||
// first convert all of the slashes
|
// first convert all of the slashes
|
||||||
|
@ -559,13 +566,6 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
|
||||||
std::vector<cmSourceFile*> classes = this->Target->GetSourceFiles();
|
std::vector<cmSourceFile*> classes = this->Target->GetSourceFiles();
|
||||||
|
|
||||||
std::set<cmSourceGroup*> groupsUsed;
|
std::set<cmSourceGroup*> groupsUsed;
|
||||||
std::vector<cmSourceFile*> clCompile;
|
|
||||||
std::vector<cmSourceFile*> customBuild;
|
|
||||||
std::vector<cmSourceFile*> none;
|
|
||||||
std::vector<cmSourceFile*> headers;
|
|
||||||
std::vector<cmSourceFile*> idls;
|
|
||||||
std::vector<cmSourceFile*> resource;
|
|
||||||
|
|
||||||
for(std::vector<cmSourceFile*>::const_iterator s = classes.begin();
|
for(std::vector<cmSourceFile*>::const_iterator s = classes.begin();
|
||||||
s != classes.end(); s++)
|
s != classes.end(); s++)
|
||||||
{
|
{
|
||||||
|
@ -574,40 +574,6 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
|
||||||
cmSourceGroup& sourceGroup =
|
cmSourceGroup& sourceGroup =
|
||||||
this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
|
this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
|
||||||
groupsUsed.insert(&sourceGroup);
|
groupsUsed.insert(&sourceGroup);
|
||||||
const char* lang = sf->GetLanguage();
|
|
||||||
bool header = (*s)->GetPropertyAsBool("HEADER_FILE_ONLY")
|
|
||||||
|| this->GlobalGenerator->IgnoreFile
|
|
||||||
((*s)->GetExtension().c_str());
|
|
||||||
std::string ext =
|
|
||||||
cmSystemTools::LowerCase((*s)->GetExtension());
|
|
||||||
if(!lang)
|
|
||||||
{
|
|
||||||
lang = "None";
|
|
||||||
}
|
|
||||||
if(header)
|
|
||||||
{
|
|
||||||
headers.push_back(sf);
|
|
||||||
}
|
|
||||||
else if(lang[0] == 'C')
|
|
||||||
{
|
|
||||||
clCompile.push_back(sf);
|
|
||||||
}
|
|
||||||
else if(strcmp(lang, "RC") == 0)
|
|
||||||
{
|
|
||||||
resource.push_back(sf);
|
|
||||||
}
|
|
||||||
else if(sf->GetCustomCommand())
|
|
||||||
{
|
|
||||||
customBuild.push_back(sf);
|
|
||||||
}
|
|
||||||
else if(ext == "idl")
|
|
||||||
{
|
|
||||||
idls.push_back(sf);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
none.push_back(sf);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this->AddMissingSourceGroups(groupsUsed, sourceGroups);
|
this->AddMissingSourceGroups(groupsUsed, sourceGroups);
|
||||||
|
@ -629,11 +595,11 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
|
||||||
"xmlns=\"http://schemas.microsoft.com/"
|
"xmlns=\"http://schemas.microsoft.com/"
|
||||||
"developer/msbuild/2003\">\n",
|
"developer/msbuild/2003\">\n",
|
||||||
0);
|
0);
|
||||||
this->WriteGroupSources("ClCompile", clCompile, sourceGroups);
|
for(ToolSourceMap::const_iterator ti = this->Tools.begin();
|
||||||
this->WriteGroupSources("ClInclude", headers, sourceGroups);
|
ti != this->Tools.end(); ++ti)
|
||||||
this->WriteGroupSources("ResourceCompile", resource, sourceGroups);
|
{
|
||||||
this->WriteGroupSources("Midl", idls, sourceGroups);
|
this->WriteGroupSources(ti->first.c_str(), ti->second, sourceGroups);
|
||||||
this->WriteGroupSources("CustomBuild", customBuild, sourceGroups);
|
}
|
||||||
|
|
||||||
// Add object library contents as external objects.
|
// Add object library contents as external objects.
|
||||||
std::vector<std::string> objs;
|
std::vector<std::string> objs;
|
||||||
|
@ -690,7 +656,6 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
|
||||||
this->WriteString("</Filter>\n", 2);
|
this->WriteString("</Filter>\n", 2);
|
||||||
}
|
}
|
||||||
this->WriteString("</ItemGroup>\n", 1);
|
this->WriteString("</ItemGroup>\n", 1);
|
||||||
this->WriteGroupSources("None", none, sourceGroups);
|
|
||||||
this->WriteString("</Project>\n", 0);
|
this->WriteString("</Project>\n", 0);
|
||||||
// restore stream pointer
|
// restore stream pointer
|
||||||
this->BuildFileStream = save;
|
this->BuildFileStream = save;
|
||||||
|
@ -750,32 +715,20 @@ cmVisualStudio10TargetGenerator::AddMissingSourceGroups(
|
||||||
void
|
void
|
||||||
cmVisualStudio10TargetGenerator::
|
cmVisualStudio10TargetGenerator::
|
||||||
WriteGroupSources(const char* name,
|
WriteGroupSources(const char* name,
|
||||||
std::vector<cmSourceFile*> const& sources,
|
ToolSources const& sources,
|
||||||
std::vector<cmSourceGroup>& sourceGroups)
|
std::vector<cmSourceGroup>& sourceGroups)
|
||||||
{
|
{
|
||||||
this->WriteString("<ItemGroup>\n", 1);
|
this->WriteString("<ItemGroup>\n", 1);
|
||||||
for(std::vector<cmSourceFile*>::const_iterator s = sources.begin();
|
for(ToolSources::const_iterator s = sources.begin();
|
||||||
s != sources.end(); ++s)
|
s != sources.end(); ++s)
|
||||||
{
|
{
|
||||||
cmSourceFile* sf = *s;
|
cmSourceFile* sf = s->SourceFile;
|
||||||
if(sf->GetExtension() == "obj")
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
std::string const& source = sf->GetFullPath();
|
std::string const& source = sf->GetFullPath();
|
||||||
cmSourceGroup& sourceGroup =
|
cmSourceGroup& sourceGroup =
|
||||||
this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
|
this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
|
||||||
const char* filter = sourceGroup.GetFullName();
|
const char* filter = sourceGroup.GetFullName();
|
||||||
this->WriteString("<", 2);
|
this->WriteString("<", 2);
|
||||||
std::string path = source;
|
std::string path = this->ConvertPath(source, s->RelativePath);
|
||||||
// custom command sources must use relative paths or they will
|
|
||||||
// not show up in the GUI.
|
|
||||||
if(sf->GetCustomCommand())
|
|
||||||
{
|
|
||||||
path = cmSystemTools::RelativePath(
|
|
||||||
this->Makefile->GetCurrentOutputDirectory(),
|
|
||||||
source.c_str());
|
|
||||||
}
|
|
||||||
this->ConvertToWindowsSlash(path);
|
this->ConvertToWindowsSlash(path);
|
||||||
(*this->BuildFileStream) << name << " Include=\""
|
(*this->BuildFileStream) << name << " Include=\""
|
||||||
<< path;
|
<< path;
|
||||||
|
@ -796,15 +749,47 @@ WriteGroupSources(const char* name,
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmVisualStudio10TargetGenerator::WriteSource(
|
void cmVisualStudio10TargetGenerator::WriteSource(
|
||||||
const char* tool, cmSourceFile* sf, bool end)
|
const char* tool, cmSourceFile* sf, const char* end)
|
||||||
{
|
{
|
||||||
std::string sourceFile = sf->GetFullPath();
|
// Visual Studio tools append relative paths to the current dir, as in:
|
||||||
// do not use a relative path here because it means that you
|
//
|
||||||
// can not use as long a path to the file.
|
// c:\path\to\current\dir\..\..\..\relative\path\to\source.c
|
||||||
|
//
|
||||||
|
// and fail if this exceeds the maximum allowed path length. Our path
|
||||||
|
// conversion uses full paths outside the build tree to allow deeper trees.
|
||||||
|
bool forceRelative = false;
|
||||||
|
std::string sourceFile = this->ConvertPath(sf->GetFullPath(), false);
|
||||||
|
if(this->LocalGenerator->GetVersion() == cmLocalVisualStudioGenerator::VS10
|
||||||
|
&& cmSystemTools::FileIsFullPath(sourceFile.c_str()))
|
||||||
|
{
|
||||||
|
// Normal path conversion resulted in a full path. VS 10 (but not 11)
|
||||||
|
// refuses to show the property page in the IDE for a source file with a
|
||||||
|
// full path (not starting in a '.' or '/' AFAICT). CMake <= 2.8.4 used a
|
||||||
|
// relative path but to allow deeper build trees CMake 2.8.[5678] used a
|
||||||
|
// full path except for custom commands. Custom commands do not work
|
||||||
|
// without a relative path, but they do not seem to be involved in tools
|
||||||
|
// with the above behavior. For other sources we now use a relative path
|
||||||
|
// when the combined path will not be too long so property pages appear.
|
||||||
|
std::string sourceRel = this->ConvertPath(sf->GetFullPath(), true);
|
||||||
|
size_t const maxLen = 250;
|
||||||
|
if(sf->GetCustomCommand() ||
|
||||||
|
((strlen(this->Makefile->GetCurrentOutputDirectory()) + 1 +
|
||||||
|
sourceRel.length()) <= maxLen))
|
||||||
|
{
|
||||||
|
forceRelative = true;
|
||||||
|
sourceFile = sourceRel;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->GlobalGenerator->PathTooLong(this->Target, sf, sourceRel);
|
||||||
|
}
|
||||||
|
}
|
||||||
this->ConvertToWindowsSlash(sourceFile);
|
this->ConvertToWindowsSlash(sourceFile);
|
||||||
this->WriteString("<", 2);
|
this->WriteString("<", 2);
|
||||||
(*this->BuildFileStream ) << tool <<
|
(*this->BuildFileStream ) << tool <<
|
||||||
" Include=\"" << sourceFile << (end? "\" />\n" : "\" ");
|
" Include=\"" << sourceFile << "\"" << (end? end : " />\n");
|
||||||
|
ToolSource toolSource = {sf, forceRelative};
|
||||||
|
this->Tools[tool].push_back(toolSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmVisualStudio10TargetGenerator::WriteSources(
|
void cmVisualStudio10TargetGenerator::WriteSources(
|
||||||
|
@ -836,7 +821,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
|
||||||
bool cl = strcmp(lang, "C") == 0 || strcmp(lang, "CXX") == 0;
|
bool cl = strcmp(lang, "C") == 0 || strcmp(lang, "CXX") == 0;
|
||||||
bool rc = strcmp(lang, "RC") == 0;
|
bool rc = strcmp(lang, "RC") == 0;
|
||||||
const char* tool = cl? "ClCompile" : (rc? "ResourceCompile" : "None");
|
const char* tool = cl? "ClCompile" : (rc? "ResourceCompile" : "None");
|
||||||
this->WriteSource(tool, *si, false);
|
this->WriteSource(tool, *si, " ");
|
||||||
// ouput any flags specific to this source file
|
// ouput any flags specific to this source file
|
||||||
if(cl && this->OutputSourceSpecificFlags(*si))
|
if(cl && this->OutputSourceSpecificFlags(*si))
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,11 +43,19 @@ public:
|
||||||
);
|
);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct ToolSource
|
||||||
|
{
|
||||||
|
cmSourceFile* SourceFile;
|
||||||
|
bool RelativePath;
|
||||||
|
};
|
||||||
|
struct ToolSources: public std::vector<ToolSource> {};
|
||||||
|
|
||||||
|
std::string ConvertPath(std::string const& path, bool forceRelative);
|
||||||
void ConvertToWindowsSlash(std::string& s);
|
void ConvertToWindowsSlash(std::string& s);
|
||||||
void WriteString(const char* line, int indentLevel);
|
void WriteString(const char* line, int indentLevel);
|
||||||
void WriteProjectConfigurations();
|
void WriteProjectConfigurations();
|
||||||
void WriteProjectConfigurationValues();
|
void WriteProjectConfigurationValues();
|
||||||
void WriteSource(const char* tool, cmSourceFile* sf, bool end = true);
|
void WriteSource(const char* tool, cmSourceFile* sf, const char* end = 0);
|
||||||
void WriteSources(const char* tool, std::vector<cmSourceFile*> const&);
|
void WriteSources(const char* tool, std::vector<cmSourceFile*> const&);
|
||||||
void WriteAllSources();
|
void WriteAllSources();
|
||||||
void WriteDotNetReferences();
|
void WriteDotNetReferences();
|
||||||
|
@ -77,8 +85,7 @@ private:
|
||||||
void WriteEvents(std::string const& configName);
|
void WriteEvents(std::string const& configName);
|
||||||
void WriteEvent(const char* name, std::vector<cmCustomCommand> & commands,
|
void WriteEvent(const char* name, std::vector<cmCustomCommand> & commands,
|
||||||
std::string const& configName);
|
std::string const& configName);
|
||||||
void WriteGroupSources(const char* name,
|
void WriteGroupSources(const char* name, ToolSources const& sources,
|
||||||
std::vector<cmSourceFile*> const& sources,
|
|
||||||
std::vector<cmSourceGroup>& );
|
std::vector<cmSourceGroup>& );
|
||||||
void AddMissingSourceGroups(std::set<cmSourceGroup*>& groupsUsed,
|
void AddMissingSourceGroups(std::set<cmSourceGroup*>& groupsUsed,
|
||||||
const std::vector<cmSourceGroup>& allGroups);
|
const std::vector<cmSourceGroup>& allGroups);
|
||||||
|
@ -99,6 +106,9 @@ private:
|
||||||
cmGeneratedFileStream* BuildFileStream;
|
cmGeneratedFileStream* BuildFileStream;
|
||||||
cmLocalVisualStudio7Generator* LocalGenerator;
|
cmLocalVisualStudio7Generator* LocalGenerator;
|
||||||
std::set<cmSourceFile*> SourcesVisited;
|
std::set<cmSourceFile*> SourcesVisited;
|
||||||
|
|
||||||
|
typedef std::map<cmStdString, ToolSources> ToolSourceMap;
|
||||||
|
ToolSourceMap Tools;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue