MantisBT - CMake
View Issue Details
0010481CMakeCMakepublic2010-03-29 14:182016-06-10 14:31
Conrad 
Bill Hoffman 
normalmajoralways
closedmoved 
CMake-2-8 
 
0010481: *.vcxproj.filters files for Visual Studio 2010 RC should only be modified / get new timestamp if content changes
CMake seems to generate <project>.vcxproj.filters files in addition to the regular <project>.vcxproj project files. From their contents these appear to be rules about how to organize files within folders in a project, and may result from using SOURCE_GROUPS in our CMake files.

Every time CMake reruns to regenerate the .sln/.vcxproj files, these files get regenerated, and Visual Studio asks whether or not to reload them - this is problematic when you have 100+ projects in your solution and have to respond to each dialog.

CMake already does an excellent job of only modifying the .vcproj/.vcxproj files when their content actually changes. Suggest doing the same thing for the .vcxproj.filters files.
No tags attached.
related to 0010502closed Brad King *.vcxproj files for Visual Studio 2010 RC should only be modified / get new timestamp if content changes 
related to 0010589closed  Spurious re-running of CMake in VS2010 Qt-based projects 
patch 0001-fix-permanent-vs10-project-filters-modification.patch (3,157) 2014-11-07 14:02
https://public.kitware.com/Bug/file/5288/0001-fix-permanent-vs10-project-filters-modification.patch
Issue History
2010-03-29 14:18ConradNew Issue
2010-03-30 02:37ConradNote Added: 0020031
2010-04-01 17:54ConradNote Added: 0020053
2010-04-02 16:10ConradNote Added: 0020066
2010-04-23 15:47Vladislav VaintroubNote Added: 0020381
2010-05-14 18:17David ColeStatusnew => assigned
2010-05-14 18:17David ColeAssigned To => Bill Hoffman
2010-05-14 18:19David ColeNote Added: 0020746
2010-05-14 18:20David ColeNote Added: 0020747
2010-05-14 18:21David ColeRelationship addedrelated to 0010502
2010-05-14 18:21David ColeRelationship addedrelated to 0010589
2010-07-10 21:13ConradNote Added: 0021346
2014-11-07 14:02Nikolay ShelukhinFile Added: 0001-fix-permanent-vs10-project-filters-modification.patch
2014-11-07 14:08Nikolay ShelukhinNote Added: 0037162
2016-06-10 14:27Kitware RobotNote Added: 0041675
2016-06-10 14:27Kitware RobotStatusassigned => resolved
2016-06-10 14:27Kitware RobotResolutionopen => moved
2016-06-10 14:31Kitware RobotStatusresolved => closed

Notes
(0020031)
Conrad   
2010-03-30 02:37   
I just checked out the latest CMake code and managed to fix this.

All the right pieces are there, so I just had to add one line to cmVisualStudio10TargetGenerator.cxx. Right after the line:
  this->BuildFileStream = & fout;
add:
  this->BuildFileStream->SetCopyIfDifferent(true);

I'm new to git and probably don't have commit authority.
(0020053)
Conrad   
2010-04-01 17:54   
The above "SetCopyIfDifferent(true);" code was necessary but not sufficient. Contents of the .vcxproj.filters file are stored in cmVisualStudio10TargetGenerator.cxx as a cmGlobalGenerator::TargetDependSet, which is an std::set< T* >. Sets by default are ordered by pointer value, which is essentially random and at the mercy of malloc(). Therefore often when CMake is rerun, the .vcxproj.filters file would show as changed, thus constantly prompting the user to reload the files, even though only the ordering of items in the list had changed.

To fix this, in cmVisualStudio10TargetGenerator::WriteProjectReferences(), change:

  this->WriteString("<ItemGroup>\n", 1);
  for( cmGlobalGenerator::TargetDependSet::const_iterator i = depends.begin();
       i != depends.end(); ++i)
    {

to:


  // We are writing a Visual Studio .vcxproj file which may be
  // currently open in Visual Studio. Visual Studio will notice if the file
  // changes and prompt the user to reload it, which is very annoying when
  // nothing has actually changed. We already use SetCopyIfDifferent(true)
  // on the output stream, but if the order in which items are listed in the
  // file changes, the file will be considered different and be reloaded.
  //
  // std::set< T* > by default orders by pointer value, which is at the
  // mercy of malloc() and essentially random. Instead sort by name, so
  // that ordering is consistent from one CMake run to the next.
  typedef std::map< std::string, cmTarget* > SortedTargetDependMap;
  SortedTargetDependMap orderedDepends;
  for( cmGlobalGenerator::TargetDependSet::const_iterator i = depends.begin();
       i != depends.end(); ++i)
    {
      orderedDepends[(*i)->GetName()] = (*i);
    }

  this->WriteString("<ItemGroup>\n", 1);
  for( SortedTargetDependMap::const_iterator i = orderedDepends.begin();
       i != orderedDepends.end(); ++i)
    {
    cmTarget* dt = (*i).second;


Also #include <map> at the top of the file...
(0020066)
Conrad   
2010-04-02 16:10   
I just stumbled upon the protected "class OrderedTargetDependSet" in the "protected:" section of cmGlobalVisualStudioGenerator.h.

So a cleaner and simpler solution is:

1. Move "struct TargetCompare" and "class OrderedTargetDependSet" from the protected to the public section of cmGlobalVisualStudioGenerator.h.

2. Change the first few lines of cmVisualStudio10TargetGenerator::WriteProjectReferences() to:

  // Must sort dependencies so they show up in a consistent order every
  // time CMake is rerun. Otherwise users get prompted to reload the
  // *.vcxproj.filters files constantly.
  cmGlobalVisualStudioGenerator::OrderedTargetDependSet depends
    = this->GlobalGenerator->GetTargetDirectDepends(*this->Target);

  this->WriteString("<ItemGroup>\n", 1);
  for( cmGlobalVisualStudioGenerator::OrderedTargetDependSet::const_iterator i = depends.begin();
       i != depends.end(); ++i)
    {
    cmTarget* dt = *i;

Obviously we also need the:
  this->BuildFileStream->SetCopyIfDifferent(true);
fix described in my first note.
(0020381)
Vladislav Vaintroub   
2010-04-23 15:47   
Yep, this is painful. I do have 70+ projects and I did not even try to count how many "ok" buttons I need to push after "cmake ." (guess around 150, once reload dialog for filters, and another one for projects)
(0020746)
David Cole   
2010-05-14 18:19   
Bill, the code that I committed today may only be a partial fix... According to the other notes here, we may also have to order things differently...?

Since I'm on vacation next week, I'm assigning to you. If it can be dealt with the week after or later, then feel free to assign back to me.

Thanks,
Dave
(0020747)
David Cole   
2010-05-14 18:20   
Partially? fixed by this commit to git master of CMake:

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7220df021be73cba540c72fcac86e59b84797375 [^]
(0021346)
Conrad   
2010-07-10 21:13   
I just wanted to point out that the 2010-05-14 fix is insufficient, as I noted above, because the entries in the generated files are not written in a consistent order, so BuildFileStream correctly decides that the files are different from their predecessors.

I think the best fix is the one I pointed out in my 2010-04-02 note. It uses the existing tool for ordering entries within a project (class OrderedTargetDependSet) and really only requires a few lines of extra code to prevent the *.vcxproj.filters files from being constantly regenerated.
(0037162)
Nikolay Shelukhin   
2014-11-07 14:08   
The problem seems to be not fixed completely.
Add a patch (0001-fix-permanent-vs10-project-filters-modification.patch) that fixes random order of 'Filter' entries.

<Filter Include="...">
  <UniqueIdentifier>...</UniqueIdentifier>
</Filter>
(0041675)
Kitware Robot   
2016-06-10 14:27   
Resolving issue as `moved`.

This issue tracker is no longer used. Further discussion of this issue may take place in the current CMake Issues page linked in the banner at the top of this page.