MantisBT - CMake
View Issue Details
0010502CMakeCMakepublic2010-04-01 18:092010-10-26 16:30
Conrad 
Brad King 
highmajoralways
closedfixed 
CMake-2-8 
CMake 2.8.3CMake 2.8.3 
0010502: *.vcxproj files for Visual Studio 2010 RC should only be modified / get new timestamp if content changes
See also Note 0000002 at Issue# 0010481.

Writing the .vcxproj project files uses "SetCopyIfDifferent(true);", which is necessary but not sufficient. Some contents of the .vcxproj file are stored in cmVisualStudio10TargetGenerator.cxx as std::set< pointer >. Sets of pointers 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 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, we sort the items before iterating through them. There are a million ways to do this, but I chose putting them into std::map< std::string, pointer > and iterating over the map. (Another option would be

In cmVisualStudio10TargetGenerator::WriteGroups(), change:
  
  std::set<cmSourceGroup*> groupsUsed;
  std::vector<cmSourceFile*> clCompile;
  std::vector<cmSourceFile*> customBuild;
  std::vector<cmSourceFile*> none;
  std::vector<cmSourceFile*> headers;
  std::vector<cmSourceFile*> resource;
  
  for(std::vector<cmSourceFile*>::const_iterator s = classes.begin();
      s != classes.end(); s++)
    {
    cmSourceFile* sf = *s;
    std::string const& source = sf->GetFullPath();
    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());

to:

  // We are writing a Visual Studio .vcxproj.filters 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, cmSourceFile*> OrderedClassesMap;
  OrderedClassesMap orderedClasses;
  for( std::vector<cmSourceFile*>::const_iterator i = classes.begin();
       i != classes.end(); ++i)
    {
    orderedClasses[(*i)->GetFullPath()] = (*i);
    }

  typedef std::map< std::string, cmSourceGroup*> OrderedGroupsMap;
  OrderedGroupsMap groupsUsed;
  std::vector<cmSourceFile*> clCompile;
  std::vector<cmSourceFile*> customBuild;
  std::vector<cmSourceFile*> none;
  std::vector<cmSourceFile*> headers;
  std::vector<cmSourceFile*> resource;
  
  for( OrderedClassesMap::const_iterator s = orderedClasses.begin();
       s != orderedClasses.end(); s++)
    {
    cmSourceFile* sf = (*s).second;
    std::string const& source = sf->GetFullPath();
    cmSourceGroup& sourceGroup =
      this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
    groupsUsed[sourceGroup.GetName()] = (&sourceGroup);
    const char* lang = sf->GetLanguage();
    bool header = sf->GetPropertyAsBool("HEADER_FILE_ONLY")
      || this->GlobalGenerator->IgnoreFile
      (sf->GetExtension().c_str());

Also further down in that function change:

  for(std::set<cmSourceGroup*>::iterator g = groupsUsed.begin();
      g != groupsUsed.end(); ++g)
    {
    cmSourceGroup* sg = *g;

to:

  for(OrderedGroupsMap::iterator g = groupsUsed.begin();
      g != groupsUsed.end(); ++g)
    {
    cmSourceGroup* sg = (*g).second;

Also #include <map> at the top of the file.

This code is also being submitted on a 5 1/4 floppy for incorporation into SCCS per today's instructions from Bill Hoffman.
No tags attached.
related to 0010481closed Bill Hoffman *.vcxproj.filters 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 
Issue History
2010-04-01 18:09ConradNew Issue
2010-05-14 18:21David ColeRelationship addedrelated to 0010481
2010-05-14 18:22David ColeRelationship addedrelated to 0010589
2010-07-13 09:28Bill HoffmanStatusnew => assigned
2010-07-13 09:28Bill HoffmanAssigned To => David Cole
2010-09-09 17:46David ColePrioritynormal => high
2010-10-07 09:53Brad KingAssigned ToDavid Cole => Brad King
2010-10-07 10:15Brad KingNote Added: 0022434
2010-10-07 10:15Brad KingStatusassigned => closed
2010-10-07 10:15Brad KingResolutionopen => fixed
2010-10-26 16:30David ColeFixed in Version => CMake 2.8.3
2010-10-26 16:30David ColeTarget Version => CMake 2.8.3

Notes
(0022434)
Brad King   
2010-10-07 10:15   
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=973df7c0 [^]