summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorDavid Cole <david.cole@kitware.com>2012-05-01 18:09:22 (GMT)
committerCMake Topic Stage <kwrobot@kitware.com>2012-05-01 18:09:22 (GMT)
commit28de11291a257428685eb5739298dfe20b30f795 (patch)
tree7f66eb7323a0219a62a64a733ab51af383ab9bfc /Source
parentc75f404065590d029d91779e4b113340303559f9 (diff)
parentd931ce9fe0c26cfddb766901cfd1ccbc9def71c7 (diff)
downloadCMake-28de11291a257428685eb5739298dfe20b30f795.zip
CMake-28de11291a257428685eb5739298dfe20b30f795.tar.gz
CMake-28de11291a257428685eb5739298dfe20b30f795.tar.bz2
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 10 4248132 VS10: Convert paths normally unless forced to relative c2ba6ba VS10: Simplify vcxproj.filter file generation 4f2d9d2 VS10: Refactor custom commands to use WriteSource
Diffstat (limited to 'Source')
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx48
-rw-r--r--Source/cmGlobalVisualStudio10Generator.h14
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx139
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h16
4 files changed, 137 insertions, 80 deletions
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 28d738a..18a786d 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -13,6 +13,7 @@
#include "cmGlobalVisualStudio10Generator.h"
#include "cmLocalVisualStudio10Generator.h"
#include "cmMakefile.h"
+#include "cmSourceFile.h"
#include "cmake.h"
@@ -51,6 +52,38 @@ cmLocalGenerator *cmGlobalVisualStudio10Generator::CreateLocalGenerator()
}
//----------------------------------------------------------------------------
+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
::GetDocumentation(cmDocumentationEntry& entry) const
{
@@ -230,3 +263,18 @@ cmGlobalVisualStudio10Generator
ruleFile += ".rule";
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;
+ }
+}
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index e2cc14e..4236563 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -46,6 +46,8 @@ public:
///! create the correct local generator
virtual cmLocalGenerator *CreateLocalGenerator();
+ virtual void Generate();
+
/**
* Try to determine system infomation such as shared library
* extension, pthreads, byte order etc.
@@ -79,10 +81,22 @@ public:
/** Generate an <output>.rule file path for a given command output. */
virtual std::string GenerateRuleFile(std::string const& output) const;
+ void PathTooLong(cmTarget* target, cmSourceFile* sf,
+ std::string const& sfRel);
protected:
virtual const char* GetIDEVersion() { return "10.0"; }
std::string PlatformToolset;
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
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 9c25b0c..9a97ab0 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -491,14 +491,9 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source,
std::vector<std::string> *configs =
static_cast<cmGlobalVisualStudio7Generator *>
(this->GlobalGenerator)->GetConfigurations();
- this->WriteString("<CustomBuild Include=\"", 2);
- // custom command have to use relative paths or they do not
- // show up in the GUI
- std::string path = cmSystemTools::RelativePath(
- this->Makefile->GetCurrentOutputDirectory(),
- sourcePath.c_str());
- this->ConvertToWindowsSlash(path);
- (*this->BuildFileStream ) << path << "\">\n";
+
+ this->WriteSource("CustomBuild", source, ">\n");
+
for(std::vector<std::string>::iterator i = configs->begin();
i != configs->end(); ++i)
{
@@ -541,6 +536,18 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source,
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)
{
// first convert all of the slashes
@@ -559,13 +566,6 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
std::vector<cmSourceFile*> classes = this->Target->GetSourceFiles();
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();
s != classes.end(); s++)
{
@@ -574,40 +574,6 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
cmSourceGroup& sourceGroup =
this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
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);
@@ -629,11 +595,11 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
"xmlns=\"http://schemas.microsoft.com/"
"developer/msbuild/2003\">\n",
0);
- this->WriteGroupSources("ClCompile", clCompile, sourceGroups);
- this->WriteGroupSources("ClInclude", headers, sourceGroups);
- this->WriteGroupSources("ResourceCompile", resource, sourceGroups);
- this->WriteGroupSources("Midl", idls, sourceGroups);
- this->WriteGroupSources("CustomBuild", customBuild, sourceGroups);
+ for(ToolSourceMap::const_iterator ti = this->Tools.begin();
+ ti != this->Tools.end(); ++ti)
+ {
+ this->WriteGroupSources(ti->first.c_str(), ti->second, sourceGroups);
+ }
// Add object library contents as external objects.
std::vector<std::string> objs;
@@ -690,7 +656,6 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
this->WriteString("</Filter>\n", 2);
}
this->WriteString("</ItemGroup>\n", 1);
- this->WriteGroupSources("None", none, sourceGroups);
this->WriteString("</Project>\n", 0);
// restore stream pointer
this->BuildFileStream = save;
@@ -750,32 +715,20 @@ cmVisualStudio10TargetGenerator::AddMissingSourceGroups(
void
cmVisualStudio10TargetGenerator::
WriteGroupSources(const char* name,
- std::vector<cmSourceFile*> const& sources,
+ ToolSources const& sources,
std::vector<cmSourceGroup>& sourceGroups)
{
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)
{
- cmSourceFile* sf = *s;
- if(sf->GetExtension() == "obj")
- {
- continue;
- }
+ cmSourceFile* sf = s->SourceFile;
std::string const& source = sf->GetFullPath();
cmSourceGroup& sourceGroup =
this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
const char* filter = sourceGroup.GetFullName();
this->WriteString("<", 2);
- std::string path = source;
- // 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());
- }
+ std::string path = this->ConvertPath(source, s->RelativePath);
this->ConvertToWindowsSlash(path);
(*this->BuildFileStream) << name << " Include=\""
<< path;
@@ -796,15 +749,47 @@ WriteGroupSources(const char* name,
}
void cmVisualStudio10TargetGenerator::WriteSource(
- const char* tool, cmSourceFile* sf, bool end)
+ const char* tool, cmSourceFile* sf, const char* end)
{
- std::string sourceFile = sf->GetFullPath();
- // do not use a relative path here because it means that you
- // can not use as long a path to the file.
+ // Visual Studio tools append relative paths to the current dir, as in:
+ //
+ // 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->WriteString("<", 2);
(*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(
@@ -836,7 +821,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
bool cl = strcmp(lang, "C") == 0 || strcmp(lang, "CXX") == 0;
bool rc = strcmp(lang, "RC") == 0;
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
if(cl && this->OutputSourceSpecificFlags(*si))
{
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index 20a443b..2d5ec2a 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -43,11 +43,19 @@ public:
);
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 WriteString(const char* line, int indentLevel);
void WriteProjectConfigurations();
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 WriteAllSources();
void WriteDotNetReferences();
@@ -77,8 +85,7 @@ private:
void WriteEvents(std::string const& configName);
void WriteEvent(const char* name, std::vector<cmCustomCommand> & commands,
std::string const& configName);
- void WriteGroupSources(const char* name,
- std::vector<cmSourceFile*> const& sources,
+ void WriteGroupSources(const char* name, ToolSources const& sources,
std::vector<cmSourceGroup>& );
void AddMissingSourceGroups(std::set<cmSourceGroup*>& groupsUsed,
const std::vector<cmSourceGroup>& allGroups);
@@ -99,6 +106,9 @@ private:
cmGeneratedFileStream* BuildFileStream;
cmLocalVisualStudio7Generator* LocalGenerator;
std::set<cmSourceFile*> SourcesVisited;
+
+ typedef std::map<cmStdString, ToolSources> ToolSourceMap;
+ ToolSourceMap Tools;
};
#endif