diff --git a/Source/cmCableDefineSetCommand.cxx b/Source/cmCableDefineSetCommand.cxx index 68d2d09eb..a22c9e082 100644 --- a/Source/cmCableDefineSetCommand.cxx +++ b/Source/cmCableDefineSetCommand.cxx @@ -36,14 +36,28 @@ bool cmCableDefineSetCommand::Invoke(std::vector& args) // The first argument is the name of the set. m_SetName = *arg++; - // The rest of the arguments are the elements to be placed in the set. - for(; arg != args.end(); ++arg) + // All arguments until a "SOURCE_FILES" are the elements to be placed in + // the set. + for(; (arg != args.end()) && (*arg != "SOURCE_FILES"); ++arg) { // If the element cannot be added, return an error. // This can occur when a tag is not specified and can't be generated. if(!this->AddElement(*arg)) { return false; } } + + // If we are not at the end, the "SOURCE_FILES" keyword has been + // encountered. + if(arg != args.end()) + { + // The rest of the arguments are source files to be included in + // any package which references the set. + for(++arg; arg != args.end(); ++arg) + { + if(!this->AddSourceFile(*arg)) + { return false; } + } + } // Write this command's configuration output. this->WriteConfiguration(); @@ -65,6 +79,17 @@ void cmCableDefineSetCommand::WriteConfiguration() const // Output the code. os << indent << "" << std::endl; + for(std::vector::const_iterator e = m_SourceHeaders.begin(); + e != m_SourceHeaders.end(); ++e) + { + os << indent << " c_str() << "\"/>" << std::endl; + } + for(std::vector::const_iterator e = m_InstantiationSources.begin(); + e != m_InstantiationSources.end(); ++e) + { + os << indent << " c_str() + << "\" purpose=\"instantiate\"/>" << std::endl; + } for(Elements::const_iterator e = m_Elements.begin(); e != m_Elements.end(); ++e) { @@ -217,3 +242,59 @@ cmCableDefineSetCommand::GenerateTag(const std::string& element, return false; } + + +/** + * Add a source file associated with this set. Any package referencing + * this set will automatically include this source file. + */ +bool cmCableDefineSetCommand::AddSourceFile(const std::string& file) +{ + // We must locate the file in the include path so that we can detect + // its extension, and whether there is more than one to find. + std::string header = file+".h"; + m_Makefile->ExpandVariablesInString(header); + + // See if the file just exists here. The compiler's search path will + // locate it. + if(cmSystemTools::FileExists(header.c_str())) + { + m_SourceHeaders.push_back(header); + // See if there is a matching .txx as well. + std::string txx = file+".txx"; + m_Makefile->ExpandVariablesInString(txx); + if(cmSystemTools::FileExists(txx.c_str())) + { + m_InstantiationSources.push_back(txx); + } + return true; + } + + // We must look for the file in the include search path. + const std::vector& includeDirectories = + m_Makefile->GetIncludeDirectories(); + + for(std::vector::const_iterator dir = includeDirectories.begin(); + dir != includeDirectories.end(); ++dir) + { + std::string path = *dir + "/" + header; + m_Makefile->ExpandVariablesInString(path); + if(cmSystemTools::FileExists(path.c_str())) + { + m_SourceHeaders.push_back(path); + // See if there is a matching .txx as well. + std::string txx = *dir + "/" + file + ".txx"; + m_Makefile->ExpandVariablesInString(txx); + if(cmSystemTools::FileExists(txx.c_str())) + { + m_InstantiationSources.push_back(txx); + } + return true; + } + } + + // We couldn't locate the source file. Report the error. + std::string err = "couldn't find source file " + header; + this->SetError(err.c_str()); + return false; +} diff --git a/Source/cmCableDefineSetCommand.h b/Source/cmCableDefineSetCommand.h index db015a5fc..3a15c9db0 100644 --- a/Source/cmCableDefineSetCommand.h +++ b/Source/cmCableDefineSetCommand.h @@ -69,11 +69,14 @@ public: virtual const char* GetFullDocumentation() { return - "CABLE_DEFINE_SET(name_of_set [[tag1]:]memeber1 [[tag2]:]member2 ...)\n" + "CABLE_DEFINE_SET(name_of_set [[tag1]:]memeber1 [[tag2]:]member2 ...\n" + " [SOURCE_FILES source1 source2 ...]] )\n" "Generates a Set definition in the CABLE configuration. The sets are\n" "referenced in other CABLE commands by a '$' immediately followed by\n" "the set name (ex. $SetName). If a the \"tag:\" syntax is not used,\n" - "an attempt is made to auto-generate a meaningful tag.\n"; + "an attempt is made to auto-generate a meaningful tag. If the\n" + "SOURCE_FILES keyword is given, all arguments after it refer to header\n" + "files to be included in any package referencing the set.\n"; } cmTypeMacro(cmCableDefineSetCommand, cmCableCommand); @@ -82,6 +85,7 @@ private: void WriteConfiguration() const; bool AddElement(const std::string&); bool GenerateTag(const std::string&, std::string&); + bool AddSourceFile(const std::string&); private: typedef std::pair Element; typedef std::vector Elements; @@ -95,6 +99,16 @@ private: * The elements to be defined in the set (before $ expansion). */ Elements m_Elements; + + /** + * The source headers associated with this set. + */ + std::vector m_SourceHeaders; + + /** + * The instantiation sources associated with this set. + */ + std::vector m_InstantiationSources; };