Browse Source

ENH: add new subdirectory exclude from top option

Bill Hoffman 21 years ago
parent
commit
ddb815c125

+ 11 - 0
Source/CMakeLists.txt

@@ -550,6 +550,17 @@ IF(BUILD_TESTING)
     --test-command  test1
     )
 
+  ADD_TEST(SubDir ${CMAKE_CTEST_COMMAND}
+    --build-and-test
+    "${CMake_SOURCE_DIR}/Tests/SubDir"
+    "${CMake_BINARY_DIR}/Tests/SubDir"
+    --build-exe-dir "${CMake_BINARY_DIR}/Tests/SubDir/Executable"
+    --build-generator ${CMAKE_GENERATOR}
+    --build-makeprogram ${MAKEPROGRAM}
+    --build-project SUBDIR
+    --test-command test "${CMake_BINARY_DIR}/Tests/SubDir/ShouldBeHere"
+    )
+
   IF (APPLE)
     ADD_TEST(objc++ ${CMAKE_CTEST_COMMAND}
       --build-and-test

+ 4 - 4
Source/cmEnableTestingCommand.cxx

@@ -63,13 +63,13 @@ void cmEnableTestingCommand::FinalPass()
   if (!m_Makefile->GetSubDirectories().empty())
     {
     fout << "SUBDIRS(";
-    const std::vector<std::string>& subdirs = m_Makefile->GetSubDirectories();
-    std::vector<std::string>::const_iterator i = subdirs.begin();
-    fout << (*i).c_str();
+    const std::vector<std::pair<cmStdString, bool> >& subdirs = m_Makefile->GetSubDirectories();
+    std::vector<std::pair<cmStdString, bool> >::const_iterator i = subdirs.begin();
+    fout << (*i).first.c_str();
     ++i;
     for(; i != subdirs.end(); ++i)
       {
-      fout << " " << (*i).c_str();
+      fout << " " << i->first.c_str();
       }
     fout << ")" << std::endl << std::endl;;
     }

+ 22 - 4
Source/cmGlobalGenerator.cxx

@@ -367,7 +367,7 @@ void cmGlobalGenerator::RecursiveConfigure(cmLocalGenerator *lg,
   lg->Configure();
                                   
   // get all the subdirectories
-  std::vector<std::string> subdirs = lg->GetMakefile()->GetSubDirectories();
+  std::vector<std::pair<cmStdString, bool> > subdirs = lg->GetMakefile()->GetSubDirectories();
   float progressPiece = (endProgress - startProgress)/(1.0f+subdirs.size());
   m_CMakeInstance->UpdateProgress("Configuring",
                                   startProgress + progressPiece);
@@ -377,18 +377,19 @@ void cmGlobalGenerator::RecursiveConfigure(cmLocalGenerator *lg,
   for (i = 0; i < subdirs.size(); ++i)
     {
     cmLocalGenerator *lg2 = this->CreateLocalGenerator();
+    lg2->SetParent(lg);
     m_LocalGenerators.push_back(lg2);
     
     // add the subdir to the start output directory
     std::string outdir = lg->GetMakefile()->GetStartOutputDirectory();
     outdir += "/";
-    outdir += subdirs[i];
+    outdir += subdirs[i].first;
     lg2->GetMakefile()->SetStartOutputDirectory(outdir.c_str());
-    
+    lg2->SetExcludeAll(!subdirs[i].second);
     // add the subdir to the start source directory
     std::string currentDir = lg->GetMakefile()->GetStartDirectory();
     currentDir += "/";
-    currentDir += subdirs[i];
+    currentDir += subdirs[i].first;
     lg2->GetMakefile()->SetStartDirectory(currentDir.c_str());
     lg2->GetMakefile()->MakeStartDirectoriesCurrent();
   
@@ -537,3 +538,20 @@ void cmGlobalGenerator::GetDocumentation(cmDocumentationEntry& entry) const
   entry.brief = "";
   entry.full = "";
 }
+
+bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root, 
+                                                cmLocalGenerator* gen)
+{
+  cmLocalGenerator* cur = gen->GetParent();
+  while(cur && cur != root)
+    {
+    if(cur->GetExcludeAll())
+      {
+      return true;
+      }
+    cur = cur->GetParent();
+    }
+  return false;
+}
+
+

+ 2 - 0
Source/cmGlobalGenerator.h

@@ -106,6 +106,8 @@ public:
   
   bool GetForceUnixPaths() {return m_ForceUnixPaths;}
 protected:
+  bool IsExcluded(cmLocalGenerator* root, cmLocalGenerator* gen);
+
   bool m_ForceUnixPaths;
   cmStdString m_FindMakeProgramFile;
   cmStdString m_ConfiguredFilesPath;

+ 13 - 5
Source/cmGlobalVisualStudio6Generator.cxx

@@ -201,8 +201,10 @@ void cmGlobalVisualStudio6Generator::CollectSubprojects()
     }
 }
 
+
 // Write a DSW file to the stream
 void cmGlobalVisualStudio6Generator::WriteDSWFile(std::ostream& fout,
+                                                  cmLocalGenerator* root,
                                                   std::vector<cmLocalGenerator*>& generators)
 {
   // Write out the header for a DSW file
@@ -215,8 +217,13 @@ void cmGlobalVisualStudio6Generator::WriteDSWFile(std::ostream& fout,
   unsigned int i;
   bool doneAllBuild = false;
   bool doneRunTests = false;
+
   for(i = 0; i < generators.size(); ++i)
     {
+    if(this->IsExcluded(root, generators[i]))
+      {
+      continue;
+      }
     cmMakefile* mf = generators[i]->GetMakefile();
     
     // Get the source directory from the makefile
@@ -324,15 +331,16 @@ void cmGlobalVisualStudio6Generator::WriteDSWFile(std::ostream& fout,
   this->WriteDSWFooter(fout);
 }
 
-void cmGlobalVisualStudio6Generator::OutputDSWFile(std::vector<cmLocalGenerator*>& generators)
+void cmGlobalVisualStudio6Generator::OutputDSWFile(cmLocalGenerator* root, 
+                                                   std::vector<cmLocalGenerator*>& generators)
 {
   if(generators.size() == 0)
     {
     return;
     }
-  std::string fname = generators[0]->GetMakefile()->GetStartOutputDirectory();
+  std::string fname = root->GetMakefile()->GetStartOutputDirectory();
   fname += "/";
-  fname += generators[0]->GetMakefile()->GetProjectName();
+  fname += root->GetMakefile()->GetProjectName();
   fname += ".dsw";
   std::ofstream fout(fname.c_str());
   if(!fout)
@@ -341,7 +349,7 @@ void cmGlobalVisualStudio6Generator::OutputDSWFile(std::vector<cmLocalGenerator*
                          fname.c_str());
     return;
     }
-  this->WriteDSWFile(fout, generators);
+  this->WriteDSWFile(fout, root, generators);
 }
 
 // output the DSW file
@@ -350,7 +358,7 @@ void cmGlobalVisualStudio6Generator::OutputDSWFile()
   std::map<cmStdString, std::vector<cmLocalGenerator*> >::iterator it;
   for(it = m_SubProjectMap.begin(); it!= m_SubProjectMap.end(); ++it)
     {
-    this->OutputDSWFile(it->second);
+    this->OutputDSWFile(it->second[0], it->second);
     }
 }
 

+ 3 - 1
Source/cmGlobalVisualStudio6Generator.h

@@ -68,8 +68,10 @@ public:
    * Generate the DSW workspace file.
    */
   virtual void OutputDSWFile();
-  virtual void OutputDSWFile(std::vector<cmLocalGenerator*>& generators);
+  virtual void OutputDSWFile(cmLocalGenerator* root,
+                             std::vector<cmLocalGenerator*>& generators);
   virtual void WriteDSWFile(std::ostream& fout,
+                            cmLocalGenerator* root,
                             std::vector<cmLocalGenerator*>& generators);
 private:
   void CollectSubprojects();

+ 11 - 5
Source/cmGlobalVisualStudio7Generator.cxx

@@ -269,15 +269,16 @@ void cmGlobalVisualStudio7Generator::Generate()
   this->OutputSLNFile();
 }
 
-void cmGlobalVisualStudio7Generator::OutputSLNFile(std::vector<cmLocalGenerator*>& generators)
+void cmGlobalVisualStudio7Generator::OutputSLNFile(cmLocalGenerator* root,
+                                                   std::vector<cmLocalGenerator*>& generators)
 {
   if(generators.size() == 0)
     {
     return;
     }
-  std::string fname = generators[0]->GetMakefile()->GetStartOutputDirectory();
+  std::string fname = root->GetMakefile()->GetStartOutputDirectory();
   fname += "/";
-  fname += generators[0]->GetMakefile()->GetProjectName();
+  fname += root->GetMakefile()->GetProjectName();
   fname += ".sln";
   std::ofstream fout(fname.c_str());
   if(!fout)
@@ -286,7 +287,7 @@ void cmGlobalVisualStudio7Generator::OutputSLNFile(std::vector<cmLocalGenerator*
                          fname.c_str());
     return;
     }
-  this->WriteSLNFile(fout, generators);
+  this->WriteSLNFile(fout, root, generators);
 }
 
 // output the SLN file
@@ -295,13 +296,14 @@ void cmGlobalVisualStudio7Generator::OutputSLNFile()
   std::map<cmStdString, std::vector<cmLocalGenerator*> >::iterator it;
   for(it = m_SubProjectMap.begin(); it!= m_SubProjectMap.end(); ++it)
     {
-    this->OutputSLNFile(it->second);
+    this->OutputSLNFile(it->second[0], it->second);
     }
 }
 
 
 // Write a SLN file to the stream
 void cmGlobalVisualStudio7Generator::WriteSLNFile(std::ostream& fout,
+                                                  cmLocalGenerator* root,
                                                   std::vector<cmLocalGenerator*>& generators)
 {
   // Write out the header for a SLN file
@@ -318,6 +320,10 @@ void cmGlobalVisualStudio7Generator::WriteSLNFile(std::ostream& fout,
   unsigned int i;
   for(i = 0; i < generators.size(); ++i)
     {
+    if(this->IsExcluded(root, generators[i]))
+      {
+      continue;
+      }
     cmMakefile* mf = generators[i]->GetMakefile();
 
     // Get the source directory from the makefile

+ 4 - 2
Source/cmGlobalVisualStudio7Generator.h

@@ -83,8 +83,10 @@ public:
       
 protected:
   void CollectSubprojects();
-  virtual void OutputSLNFile(std::vector<cmLocalGenerator*>& generators);
-  virtual void WriteSLNFile(std::ostream& fout, std::vector<cmLocalGenerator*>& generators);
+  virtual void OutputSLNFile(cmLocalGenerator* root, 
+                             std::vector<cmLocalGenerator*>& generators);
+  virtual void WriteSLNFile(std::ostream& fout, cmLocalGenerator* root,
+                            std::vector<cmLocalGenerator*>& generators);
   virtual void WriteProject(std::ostream& fout, 
                             const char* name, const char* path,
                             const cmTarget &t);

+ 5 - 3
Source/cmLocalGenerator.cxx

@@ -24,6 +24,8 @@ cmLocalGenerator::cmLocalGenerator()
 {
   m_Makefile = new cmMakefile;
   m_Makefile->SetLocalGenerator(this);
+  m_ExcludeFromAll = false;
+  m_Parent = 0;
 }
 
 cmLocalGenerator::~cmLocalGenerator()
@@ -229,12 +231,12 @@ void cmLocalGenerator::GenerateInstallRules()
   cmMakefile* mf = this->GetMakefile();
   if ( !mf->GetSubDirectories().empty() )
     {
-    const std::vector<std::string>& subdirs = mf->GetSubDirectories();
-    std::vector<std::string>::const_iterator i = subdirs.begin();
+    const std::vector<std::pair<cmStdString, bool> >& subdirs = mf->GetSubDirectories();
+    std::vector<std::pair<cmStdString, bool> >::const_iterator i = subdirs.begin();
     for(; i != subdirs.end(); ++i)
       {
       std::string odir = mf->GetCurrentOutputDirectory();
-      odir += "/" + (*i);
+      odir += "/" + (*i).first;
       cmSystemTools::ConvertToUnixSlashes(odir);
       fout << "INCLUDE(" <<  odir.c_str() 
            << "/cmake_install.cmake)" << std::endl;

+ 16 - 1
Source/cmLocalGenerator.h

@@ -78,6 +78,20 @@ public:
   virtual const char* GetSafeDefinition(const char*);
 
   std::string ConvertToRelativeOutputPath(const char* p);
+  
+  // flag to determine if this project should be included in a parent project
+  bool GetExcludeAll()
+    {
+      return m_ExcludeFromAll;
+    }
+  void SetExcludeAll(bool b)
+    {
+      m_ExcludeFromAll = b;
+    }
+  
+  ///! set/get the parent generator 
+  cmLocalGenerator* GetParent(){return m_Parent;}
+  void SetParent(cmLocalGenerator* g) { m_Parent = g;}
 protected:
   virtual void AddInstallRule(std::ostream& fout, const char* dest, int type, 
     const char* files, bool optional = false);
@@ -92,7 +106,8 @@ protected:
   std::string m_HomeOutputDirectory;
   std::string m_HomeDirectory;
   std::string m_HomeOutputDirectoryNoSlash;
-
+  bool m_ExcludeFromAll;
+  cmLocalGenerator* m_Parent;
 };
 
 #endif

+ 16 - 13
Source/cmLocalUnixMakefileGenerator.cxx

@@ -1996,7 +1996,7 @@ OutputSubDirectoryVars(std::ostream& fout,
                        const char* target1,
                        const char* target2,
                        const char* depend,
-                       const std::vector<std::string>& SubDirectories,
+                       const std::vector<std::pair<cmStdString, bool> >& SubDirectories,
                        bool silent)
 {
   if(!depend)
@@ -2008,26 +2008,29 @@ OutputSubDirectoryVars(std::ostream& fout,
     return;
     }
   fout << "# Variable for making " << target << " in subdirectories.\n";
-  fout << var << " = \\\n";
+  fout << var << " = ";
   unsigned int ii;
   for(ii =0; ii < SubDirectories.size(); ii++)
     { 
-    std::string subdir = FixDirectoryName(SubDirectories[ii].c_str());
-    fout << target << "_" << subdir.c_str();
-    if(ii == SubDirectories.size()-1)
+    if(!SubDirectories[ii].second)
       {
-      fout << " \n\n";
-      }
-    else
-      {
-      fout << " \\\n";
+      continue;
       }
+    fout << " \\\n";
+    std::string subdir = FixDirectoryName(SubDirectories[ii].first.c_str());
+    fout << target << "_" << subdir.c_str();
     }
+  fout << " \n\n";
+
   fout << "# Targets for making " << target << " in subdirectories.\n";
   std::string last = "";
   for(unsigned int cc =0; cc < SubDirectories.size(); cc++)
     {
-    std::string subdir = FixDirectoryName(SubDirectories[cc].c_str());
+    if(!SubDirectories[cc].second)
+      {
+      continue;
+      }
+    std::string subdir = FixDirectoryName(SubDirectories[cc].first.c_str());
     fout << target << "_" << subdir.c_str() << ": " << depend;
     
     // Make each subdirectory depend on previous one.  This forces
@@ -2042,7 +2045,7 @@ OutputSubDirectoryVars(std::ostream& fout,
     last = subdir;
     std::string dir = m_Makefile->GetCurrentOutputDirectory();
     dir += "/";
-    dir += SubDirectories[cc];
+    dir += SubDirectories[cc].first;
     this->BuildInSubDirectory(fout, dir.c_str(),
                               target1, target2, silent);
     }
@@ -2054,7 +2057,7 @@ OutputSubDirectoryVars(std::ostream& fout,
 void cmLocalUnixMakefileGenerator::OutputSubDirectoryRules(std::ostream& fout)
 {
     // Output Sub directory build rules
-  const std::vector<std::string>& SubDirectories
+  const std::vector<std::pair<cmStdString, bool> >& SubDirectories
     = m_Makefile->GetSubDirectories();
     
   if( SubDirectories.size() == 0)

+ 1 - 1
Source/cmLocalUnixMakefileGenerator.h

@@ -159,7 +159,7 @@ protected:
                                       const char* target1,
                                       const char* target2,
                                       const char* depend,
-                                      const std::vector<std::string>&
+                                      const std::vector<std::pair<cmStdString, bool> >&
                                       SubDirectories,
                                       bool silent = false);
 

+ 15 - 3
Source/cmMakefile.cxx

@@ -142,6 +142,17 @@ void cmMakefile::PrintStringVector(const char* s, const std::vector<std::string>
   std::cout << " )\n";
 }
 
+void cmMakefile::PrintStringVector(const char* s, const std::vector<std::pair<cmStdString, bool> >& v) const
+{
+  std::cout << s << ": ( \n";
+  for(std::vector<std::pair<cmStdString, bool> >::const_iterator i = v.begin();
+      i != v.end(); ++i)
+    {
+    std::cout << i->first.c_str() << " " << i->second;
+    }
+  std::cout << " )\n";
+}
+
 
 // call print on all the classes in the makefile
 void cmMakefile::Print() const
@@ -824,13 +835,14 @@ void cmMakefile::AddLinkDirectory(const char* dir)
     }
 }
 
-void cmMakefile::AddSubDirectory(const char* sub)
+void cmMakefile::AddSubDirectory(const char* sub, bool topLevel)
 {
+  std::pair<cmStdString, bool> p(sub, topLevel);
   // make sure it isn't already there
   if (std::find(m_SubDirectories.begin(),
-                m_SubDirectories.end(), sub) == m_SubDirectories.end())  
+                m_SubDirectories.end(), p) == m_SubDirectories.end())  
     {
-    m_SubDirectories.push_back(sub);
+    m_SubDirectories.push_back(p);
     }
 }
 

+ 4 - 3
Source/cmMakefile.h

@@ -203,7 +203,7 @@ public:
   /**
    * Add a subdirectory to the build.
    */
-  void AddSubDirectory(const char*);
+  void AddSubDirectory(const char*, bool includeTopLevel=true);
 
   /**
    * Add an include directory to the build.
@@ -409,7 +409,7 @@ public:
   /**
    * Get a list of the build subdirectories.
    */
-  const std::vector<std::string>& GetSubDirectories()
+  const std::vector<std::pair<cmStdString, bool> >& GetSubDirectories()
     { 
     return m_SubDirectories;
     }
@@ -658,7 +658,7 @@ protected:
   cmTargets m_Targets;
   std::vector<cmSourceFile*> m_SourceFiles;
 
-  std::vector<std::string> m_SubDirectories; // list of sub directories
+  std::vector<std::pair<cmStdString, bool> > m_SubDirectories; // list of sub directories
   struct StringSet : public std::set<cmStdString>
   {
   };
@@ -695,6 +695,7 @@ private:
   void ReadSources(std::ifstream& fin, bool t);
   friend class cmMakeDepend;    // make depend needs direct access 
                                 // to the m_Sources array 
+  void PrintStringVector(const char* s, const std::vector<std::pair<cmStdString, bool> >& v) const;
   void PrintStringVector(const char* s, const std::vector<std::string>& v) const;
   void AddDefaultDefinitions();
   std::list<cmFunctionBlocker *> m_FunctionBlockers;

+ 7 - 1
Source/cmSubdirCommand.cxx

@@ -25,15 +25,21 @@ bool cmSubdirCommand::InitialPass(std::vector<std::string> const& args)
     return false;
     }
   bool res = true;
+  bool intoplevel = true;
 
   for(std::vector<std::string>::const_iterator i = args.begin();
       i != args.end(); ++i)
     {
+    if(*i == "EXCLUDE_FROM_ALL")
+      {
+      intoplevel = false;
+      continue;
+      }
     std::string directory = std::string(m_Makefile->GetCurrentDirectory()) + 
       "/" + i->c_str();
     if ( cmSystemTools::FileIsDirectory(directory.c_str()) )
       {
-      m_Makefile->AddSubDirectory(i->c_str());
+      m_Makefile->AddSubDirectory(i->c_str(), intoplevel);
       }
     else
       {

+ 7 - 2
Source/cmSubdirCommand.h

@@ -62,10 +62,15 @@ public:
   virtual const char* GetFullDocumentation()
     {
     return
-      "  SUBDIRS(dir1 dir2 ...)\n"
+      "  SUBDIRS(dir1 dir2 ...[EXCLUDE_FROM_ALL exclude_dir1 exclude_dir2 ...])\n"
       "Add a list of subdirectories to the build. "
       "This will cause any CMakeLists.txt files in the sub directories "
-      "to be processed by CMake.";
+      "to be processed by CMake.  Any directories after the EXCLUDE_FROM_ALL marker "
+      "will not be included in the top level makefile or project file.  This is useful"
+      " for having cmake create makefiles or projects for a set of examples in a project."
+      "You would want cmake to generated makefiles or project files for all the examples at"
+      " the same time, but you would not want them to show up in the top level project or be built"
+      " each time make is run from the top.";
     }
   
   cmTypeMacro(cmSubdirCommand, cmCommand);

+ 5 - 3
Tests/SubDir/Executable/test.cxx

@@ -1,8 +1,10 @@
 #include <stdio.h>
-#include  <io.h>
-#include  <stdio.h>
 #include  <stdlib.h>
-
+#ifdef _WIN32
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
 
 // return true if the file exists
 int FileExists(const char* filename)