diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 86e862773..bff099f18 100644 --- a/Source/CMakeLists.txt +++ b/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 diff --git a/Source/cmEnableTestingCommand.cxx b/Source/cmEnableTestingCommand.cxx index 7381df8c9..05a65456b 100644 --- a/Source/cmEnableTestingCommand.cxx +++ b/Source/cmEnableTestingCommand.cxx @@ -63,13 +63,13 @@ void cmEnableTestingCommand::FinalPass() if (!m_Makefile->GetSubDirectories().empty()) { fout << "SUBDIRS("; - const std::vector& subdirs = m_Makefile->GetSubDirectories(); - std::vector::const_iterator i = subdirs.begin(); - fout << (*i).c_str(); + const std::vector >& subdirs = m_Makefile->GetSubDirectories(); + std::vector >::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;; } diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index e22b82fcb..b09ab9da0 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -367,7 +367,7 @@ void cmGlobalGenerator::RecursiveConfigure(cmLocalGenerator *lg, lg->Configure(); // get all the subdirectories - std::vector subdirs = lg->GetMakefile()->GetSubDirectories(); + std::vector > 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; +} + + diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 3f4b1e3f2..a22bc4c44 100644 --- a/Source/cmGlobalGenerator.h +++ b/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; diff --git a/Source/cmGlobalVisualStudio6Generator.cxx b/Source/cmGlobalVisualStudio6Generator.cxx index 97789ea11..13bfad612 100644 --- a/Source/cmGlobalVisualStudio6Generator.cxx +++ b/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& 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& generators) +void cmGlobalVisualStudio6Generator::OutputDSWFile(cmLocalGenerator* root, + std::vector& 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::vectorWriteDSWFile(fout, generators); + this->WriteDSWFile(fout, root, generators); } // output the DSW file @@ -350,7 +358,7 @@ void cmGlobalVisualStudio6Generator::OutputDSWFile() std::map >::iterator it; for(it = m_SubProjectMap.begin(); it!= m_SubProjectMap.end(); ++it) { - this->OutputDSWFile(it->second); + this->OutputDSWFile(it->second[0], it->second); } } diff --git a/Source/cmGlobalVisualStudio6Generator.h b/Source/cmGlobalVisualStudio6Generator.h index 0bf0cc200..4aaa619e8 100644 --- a/Source/cmGlobalVisualStudio6Generator.h +++ b/Source/cmGlobalVisualStudio6Generator.h @@ -68,8 +68,10 @@ public: * Generate the DSW workspace file. */ virtual void OutputDSWFile(); - virtual void OutputDSWFile(std::vector& generators); + virtual void OutputDSWFile(cmLocalGenerator* root, + std::vector& generators); virtual void WriteDSWFile(std::ostream& fout, + cmLocalGenerator* root, std::vector& generators); private: void CollectSubprojects(); diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index e30271886..9feb3b8c6 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -269,15 +269,16 @@ void cmGlobalVisualStudio7Generator::Generate() this->OutputSLNFile(); } -void cmGlobalVisualStudio7Generator::OutputSLNFile(std::vector& generators) +void cmGlobalVisualStudio7Generator::OutputSLNFile(cmLocalGenerator* root, + std::vector& 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::vectorWriteSLNFile(fout, generators); + this->WriteSLNFile(fout, root, generators); } // output the SLN file @@ -295,13 +296,14 @@ void cmGlobalVisualStudio7Generator::OutputSLNFile() std::map >::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& 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 diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h index 4cd5bc274..d934ebe43 100644 --- a/Source/cmGlobalVisualStudio7Generator.h +++ b/Source/cmGlobalVisualStudio7Generator.h @@ -83,8 +83,10 @@ public: protected: void CollectSubprojects(); - virtual void OutputSLNFile(std::vector& generators); - virtual void WriteSLNFile(std::ostream& fout, std::vector& generators); + virtual void OutputSLNFile(cmLocalGenerator* root, + std::vector& generators); + virtual void WriteSLNFile(std::ostream& fout, cmLocalGenerator* root, + std::vector& generators); virtual void WriteProject(std::ostream& fout, const char* name, const char* path, const cmTarget &t); diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index a108b1387..eea1b17e3 100644 --- a/Source/cmLocalGenerator.cxx +++ b/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& subdirs = mf->GetSubDirectories(); - std::vector::const_iterator i = subdirs.begin(); + const std::vector >& subdirs = mf->GetSubDirectories(); + std::vector >::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; diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index c7e1e203b..a3017552c 100644 --- a/Source/cmLocalGenerator.h +++ b/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 diff --git a/Source/cmLocalUnixMakefileGenerator.cxx b/Source/cmLocalUnixMakefileGenerator.cxx index 936555ec8..3ca70d81d 100644 --- a/Source/cmLocalUnixMakefileGenerator.cxx +++ b/Source/cmLocalUnixMakefileGenerator.cxx @@ -1996,7 +1996,7 @@ OutputSubDirectoryVars(std::ostream& fout, const char* target1, const char* target2, const char* depend, - const std::vector& SubDirectories, + const std::vector >& 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()); + if(!SubDirectories[ii].second) + { + continue; + } + fout << " \\\n"; + std::string subdir = FixDirectoryName(SubDirectories[ii].first.c_str()); fout << target << "_" << subdir.c_str(); - if(ii == SubDirectories.size()-1) - { - fout << " \n\n"; - } - else - { - fout << " \\\n"; - } } + 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& SubDirectories + const std::vector >& SubDirectories = m_Makefile->GetSubDirectories(); if( SubDirectories.size() == 0) diff --git a/Source/cmLocalUnixMakefileGenerator.h b/Source/cmLocalUnixMakefileGenerator.h index 4cdb8b095..ec44e54dc 100644 --- a/Source/cmLocalUnixMakefileGenerator.h +++ b/Source/cmLocalUnixMakefileGenerator.h @@ -159,7 +159,7 @@ protected: const char* target1, const char* target2, const char* depend, - const std::vector& + const std::vector >& SubDirectories, bool silent = false); diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index f53b3bb10..cc1721c3e 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -142,6 +142,17 @@ void cmMakefile::PrintStringVector(const char* s, const std::vector std::cout << " )\n"; } +void cmMakefile::PrintStringVector(const char* s, const std::vector >& v) const +{ + std::cout << s << ": ( \n"; + for(std::vector >::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 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); } } diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index faa49869e..dbfe6a652 100644 --- a/Source/cmMakefile.h +++ b/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& GetSubDirectories() + const std::vector >& GetSubDirectories() { return m_SubDirectories; } @@ -658,7 +658,7 @@ protected: cmTargets m_Targets; std::vector m_SourceFiles; - std::vector m_SubDirectories; // list of sub directories + std::vector > m_SubDirectories; // list of sub directories struct StringSet : public std::set { }; @@ -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 >& v) const; void PrintStringVector(const char* s, const std::vector& v) const; void AddDefaultDefinitions(); std::list m_FunctionBlockers; diff --git a/Source/cmSubdirCommand.cxx b/Source/cmSubdirCommand.cxx index 7fcf81417..3bcd1a0e6 100644 --- a/Source/cmSubdirCommand.cxx +++ b/Source/cmSubdirCommand.cxx @@ -25,15 +25,21 @@ bool cmSubdirCommand::InitialPass(std::vector const& args) return false; } bool res = true; + bool intoplevel = true; for(std::vector::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 { diff --git a/Source/cmSubdirCommand.h b/Source/cmSubdirCommand.h index c5fda341f..fce1985c6 100644 --- a/Source/cmSubdirCommand.h +++ b/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); diff --git a/Tests/SubDir/Executable/test.cxx b/Tests/SubDir/Executable/test.cxx index 12913e8a2..f35152179 100644 --- a/Tests/SubDir/Executable/test.cxx +++ b/Tests/SubDir/Executable/test.cxx @@ -1,8 +1,10 @@ #include -#include -#include #include - +#ifdef _WIN32 +#include +#else +#include +#endif // return true if the file exists int FileExists(const char* filename)