From a91947039a025df00403be2cadba469346f274a8 Mon Sep 17 00:00:00 2001
From: Bill Hoffman <bill.hoffman@kitware.com>
Date: Mon, 9 Jan 2006 14:40:31 -0500
Subject: ENH: for all custom commands that can not be given to a target, add
 them to all targets in the current makefile

---
 Source/cmCustomCommand.cxx               |  3 ++
 Source/cmCustomCommand.h                 |  5 ++
 Source/cmLocalVisualStudio6Generator.cxx | 56 ++++++++++++++++++++--
 Source/cmLocalVisualStudio7Generator.cxx | 79 ++++++++++++++++++++++++++++++--
 Source/cmTarget.cxx                      | 10 ++++
 Tests/CustomCommand/CMakeLists.txt       | 11 ++++-
 Tests/Wrapping/CMakeLists.txt            |  7 ++-
 Tests/Wrapping/fakefluid.cxx             | 16 +++++++
 8 files changed, 177 insertions(+), 10 deletions(-)
 create mode 100644 Tests/Wrapping/fakefluid.cxx

diff --git a/Source/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx
index d677798..8d794f7 100644
--- a/Source/cmCustomCommand.cxx
+++ b/Source/cmCustomCommand.cxx
@@ -19,6 +19,7 @@
 //----------------------------------------------------------------------------
 cmCustomCommand::cmCustomCommand()
 {
+  m_Used = false;
 }
 
 //----------------------------------------------------------------------------
@@ -28,6 +29,7 @@ cmCustomCommand::cmCustomCommand(const cmCustomCommand& r):
   m_CommandLines(r.m_CommandLines),
   m_Comment(r.m_Comment)
 {
+  m_Used = false;
 }
 
 //----------------------------------------------------------------------------
@@ -40,6 +42,7 @@ cmCustomCommand::cmCustomCommand(const char* output,
   m_CommandLines(commandLines),
   m_Comment(comment?comment:"")
 {
+  m_Used = false;
 }
 
 //----------------------------------------------------------------------------
diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h
index 0a87949..966cab3 100644
--- a/Source/cmCustomCommand.h
+++ b/Source/cmCustomCommand.h
@@ -49,11 +49,16 @@ public:
   /** Get the comment string for the command.  */
   const char* GetComment() const;
 
+  /** set get the used status of the command */ 
+  void Used() { m_Used = true;}; 
+  bool IsUsed() { return m_Used;};
+ 
 private:
   std::string m_Output;
   std::vector<std::string> m_Depends;
   cmCustomCommandLines m_CommandLines;
   std::string m_Comment;
+  bool m_Used;
 };
 
 #endif
diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx
index ec81861..1e41a33 100644
--- a/Source/cmLocalVisualStudio6Generator.cxx
+++ b/Source/cmLocalVisualStudio6Generator.cxx
@@ -80,9 +80,60 @@ void cmLocalVisualStudio6Generator::OutputDSPFile()
 
   // clear project names
   m_CreatedProjectNames.clear();
-
+  // Call TraceVSDependencies on all targets
+  cmTargets &tgts = m_Makefile->GetTargets(); 
+  for(cmTargets::iterator l = tgts.begin(); 
+      l != tgts.end(); l++)
+    {
+    // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace
+    // so don't build a projectfile for it
+    if ((l->second.GetType() != cmTarget::INSTALL_FILES)
+        && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS)
+        && (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) != 0))
+      {
+      cmTarget& target = l->second;
+      target.TraceVSDependencies(target.GetName(), m_Makefile);
+      }
+    }
+  // now for all custom commands that are not used directly in a 
+  // target, add them to all targets in the current directory or
+  // makefile
+  std::vector<cmSourceFile*> & classesmf = m_Makefile->GetSourceFiles();
+  for(std::vector<cmSourceFile*>::const_iterator i = classesmf.begin(); 
+      i != classesmf.end(); i++)
+    {
+    if(cmCustomCommand* cc = (*i)->GetCustomCommand())
+      {
+      if(!cc->IsUsed())
+        {
+        for(cmTargets::iterator l = tgts.begin(); 
+            l != tgts.end(); l++)
+          {
+          if ((l->second.GetType() != cmTarget::INSTALL_FILES)
+              && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS)
+              && (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) != 0))
+            {
+            cmTarget& target = l->second;
+            bool sameAsTarget = false;
+            // make sure we don't add a custom command that depends on
+            // this target
+            for(unsigned int k =0; k < cc->GetDepends().size(); k++)
+              {
+              if(cmSystemTools::GetFilenameName(cc->GetDepends()[k]) == target.GetFullName())
+                {
+                sameAsTarget = true;
+                }
+              }
+            if(!sameAsTarget)
+              {
+              target.GetSourceFiles().push_back(*i);
+              }
+            }
+          }
+        }
+      }
+    }
   // build any targets
-  cmTargets &tgts = m_Makefile->GetTargets();
   for(cmTargets::iterator l = tgts.begin(); 
       l != tgts.end(); l++)
     {
@@ -266,7 +317,6 @@ void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream& fout,
   // trace the visual studio dependencies
   std::string name = libName;
   name += ".dsp.cmake";
-  target.TraceVSDependencies(name, m_Makefile);
 
   // We may be modifying the source groups temporarily, so make a copy.
   std::vector<cmSourceGroup> sourceGroups = m_Makefile->GetSourceGroups();
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 6a0ab0d..bb969aa 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -92,8 +92,82 @@ void cmLocalVisualStudio7Generator::OutputVCProjFile()
   // clear project names
   m_CreatedProjectNames.clear();
 
-  // build any targets
-  cmTargets &tgts = m_Makefile->GetTargets();
+  // Call TraceVSDependencies on all targets
+  cmTargets &tgts = m_Makefile->GetTargets(); 
+  for(cmTargets::iterator l = tgts.begin(); 
+      l != tgts.end(); l++)
+    {
+    // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace
+    // so don't build a projectfile for it
+    if ((l->second.GetType() != cmTarget::INSTALL_FILES)
+        && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS)
+        && (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) != 0))
+      {
+      cmTarget& target = l->second;
+      target.TraceVSDependencies(target.GetName(), m_Makefile);
+      }
+    }
+  // now for all custom commands that are not used directly in a 
+  // target, add them to all targets in the current directory or
+  // makefile
+  std::vector<cmSourceFile*> & classesmf = m_Makefile->GetSourceFiles();
+  for(std::vector<cmSourceFile*>::const_iterator i = classesmf.begin(); 
+      i != classesmf.end(); i++)
+    {
+    if(cmCustomCommand* cc = (*i)->GetCustomCommand())
+      {
+      // while we are at it, if it is a .rule file then for visual studio 7 we
+      // must generate it so that depend information works correctly
+      if ((*i)->GetSourceExtension() == "rule")
+        { 
+        std::string source = (*i)->GetFullPath();
+        if(!cmSystemTools::FileExists(source.c_str()))
+          {
+          cmSystemTools::ReplaceString(source, "$(IntDir)/", "");
+#if defined(_WIN32) || defined(__CYGWIN__)
+          std::ofstream fout(source.c_str(), 
+                             std::ios::binary | std::ios::out | std::ios::trunc);
+#else
+          std::ofstream fout(source.c_str(), 
+                             std::ios::out | std::ios::trunc);
+#endif
+          if(fout)
+            {
+            fout.write("# generated from CMake",22);
+            fout.flush();
+            fout.close();
+            }
+          }
+        }
+      if(!cc->IsUsed())
+        {
+        for(cmTargets::iterator l = tgts.begin(); 
+            l != tgts.end(); l++)
+          {
+          if ((l->second.GetType() != cmTarget::INSTALL_FILES)
+              && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS)
+              && (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) != 0))
+            {
+            cmTarget& target = l->second;
+            bool sameAsTarget = false;
+            // make sure we don't add a custom command that depends on
+            // this target
+            for(unsigned int k =0; k < cc->GetDepends().size(); k++)
+              {
+              if(cmSystemTools::GetFilenameName(cc->GetDepends()[k]) == target.GetFullName())
+                {
+                sameAsTarget = true;
+                }
+              }
+            if(!sameAsTarget)
+              {
+              target.GetSourceFiles().push_back(*i);
+              }
+            }
+          }
+        }
+      }
+    }
   for(cmTargets::iterator l = tgts.begin(); 
       l != tgts.end(); l++)
     {
@@ -968,7 +1042,6 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
   // trace the visual studio dependencies
   std::string name = libName;
   name += ".vcproj.cmake";
-  target.TraceVSDependencies(name, m_Makefile);
 
   // We may be modifying the source groups temporarily, so make a copy.
   std::vector<cmSourceGroup> sourceGroups = m_Makefile->GetSourceGroups();
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 61f5482..3480794 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -192,6 +192,16 @@ void cmTarget::TraceVSDependencies(std::string projFile,
     // finished with this SF move to the next
     srcFilesToProcess.pop();
     }
+  // mark all custom commands in the targets list of source files as used.
+  for(std::vector<cmSourceFile*>::iterator i =  m_SourceFiles.begin();
+      i != m_SourceFiles.end(); ++i)
+    {
+    cmCustomCommand* cc = (*i)->GetCustomCommand();
+    if(cc)
+      {
+      cc->Used();
+      }
+    }
 }
 
 void cmTarget::GenerateSourceFilesFromSourceLists( cmMakefile &mf)
diff --git a/Tests/CustomCommand/CMakeLists.txt b/Tests/CustomCommand/CMakeLists.txt
index 69b6d2f..3f7a999 100644
--- a/Tests/CustomCommand/CMakeLists.txt
+++ b/Tests/CustomCommand/CMakeLists.txt
@@ -3,6 +3,8 @@
 #
 PROJECT (CustomCommand)
 
+ADD_SUBDIRECTORY(GeneratedHeader)
+
 #
 # Lib and exe path
 #
@@ -133,8 +135,10 @@ ADD_CUSTOM_COMMAND(OUTPUT ${PROJECT_BINARY_DIR}/foo.c
 # auto-object-depends feature of the Makefile generator.  Currently
 # the feature does not seem to work in Visual Studio generators so
 # these dependencies are needed.
-SET_SOURCE_FILES_PROPERTIES(${PROJECT_BINARY_DIR}/foo.c PROPERTIES
-  OBJECT_DEPENDS "${PROJECT_BINARY_DIR}/doc1.h;${PROJECT_BINARY_DIR}/foo.h")
+#SET_SOURCE_FILES_PROPERTIES(${PROJECT_BINARY_DIR}/foo.c 
+#PROPERTIES
+#  OBJECT_DEPENDS "${PROJECT_BINARY_DIR}/doc1.h;${PROJECT_BINARY_DIR}/foo.h"
+#)
 
 # add the library
 ADD_EXECUTABLE(CustomCommand 
@@ -143,6 +147,9 @@ ADD_EXECUTABLE(CustomCommand
   ${PROJECT_BINARY_DIR}/generated.c
   )
 
+TARGET_LINK_LIBRARIES(CustomCommand GeneratedHeader)
+
 # must add a dependency on TDocument otherwise it might never build and 
 # the CustomCommand executable really needs doc1.h
 ADD_DEPENDENCIES(CustomCommand TDocument)
+
diff --git a/Tests/Wrapping/CMakeLists.txt b/Tests/Wrapping/CMakeLists.txt
index d8b332d..3b7684a 100644
--- a/Tests/Wrapping/CMakeLists.txt
+++ b/Tests/Wrapping/CMakeLists.txt
@@ -143,15 +143,18 @@ ENDIF (QT_FOUND AND QT_UIC_EXECUTABLE)
 SET (FLTK_SRCS
   fltk1.fl
   )
+ADD_EXECUTABLE(fakefluid fakefluid.cxx)
+GET_TARGET_PROPERTY(FLUID_LOC fakefluid LOCATION)
 SET (FLTK_WRAP_UI "On")
-SET (FLTK_FLUID_EXECUTABLE "echo")
+SET (FLTK_FLUID_EXECUTABLE "${FLUID_LOC}")
 FLTK_WRAP_UI (wraplibFLTK ${FLTK_SRCS})
 ADD_LIBRARY(wraplibFLTK ${wraplibFLTK_FLTK_UI_SRCS})
 CONFIGURE_FILE(
   ${Wrapping_SOURCE_DIR}/fltk1.fl
   ${Wrapping_BINARY_DIR}/fltk1.cxx
   COPYONLY)
-
+ADD_DEPENDENCIES(wraplibFLTK fakefluid)
+ADD_DEPENDENCIES(fakefluid Wrap)
 #
 # Mangled Mesa
 #
diff --git a/Tests/Wrapping/fakefluid.cxx b/Tests/Wrapping/fakefluid.cxx
new file mode 100644
index 0000000..25c6e93
--- /dev/null
+++ b/Tests/Wrapping/fakefluid.cxx
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <string.h>
+int main(int ac, char** av)
+{
+  for(int i =0; i < ac; ++i)
+    {
+    if(strcmp(av[i], "-o") == 0)
+      {
+      FILE* file = fopen(av[i+1], "w");
+      fprintf(file, "// hello\n");
+      fclose(file);
+      return 0;
+      }
+    }
+  return 0;
+}
-- 
cgit v0.12