From 3200bfbf4cf65ebed19686fe7a8ef85457fbd4c9 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 15 Aug 2002 14:39:21 -0400 Subject: [PATCH] ENH: Improved generated instantiator to use extern declarations to wrappers around the New() methods. This avoids the need to include each class's header in an instantiator source. The instantiator class implementations can now fit in a single source file that compiles quickly. --- Source/cmVTKMakeInstantiatorCommand.cxx | 164 ++++++------------------ Source/cmVTKMakeInstantiatorCommand.h | 15 +-- 2 files changed, 41 insertions(+), 138 deletions(-) diff --git a/Source/cmVTKMakeInstantiatorCommand.cxx b/Source/cmVTKMakeInstantiatorCommand.cxx index bf8466e59..7e3ab54b1 100644 --- a/Source/cmVTKMakeInstantiatorCommand.cxx +++ b/Source/cmVTKMakeInstantiatorCommand.cxx @@ -35,7 +35,6 @@ cmVTKMakeInstantiatorCommand std::vector inSourceLists; m_ExportMacro = "-"; - unsigned int groupSize = 10; bool includesMode = false; // Find the path of the files to be generated. @@ -44,20 +43,7 @@ cmVTKMakeInstantiatorCommand for(unsigned int i=2;i < args.size();++i) { - if(args[i] == "GROUP_SIZE") - { - includesMode = false; - if(++i < args.size()) - { - groupSize = atoi(args[i].c_str()); - } - else - { - this->SetError("GROUP_SIZE option used without value."); - return false; - } - } - else if(args[i] == "HEADER_LOCATION") + if(args[i] == "HEADER_LOCATION") { includesMode = false; if(++i < args.size()) @@ -160,56 +146,11 @@ cmVTKMakeInstantiatorCommand m_Makefile->AddSource(file); sourceListValue += file.GetSourceName() + ".cxx"; } - - size_t numClasses = m_Classes.size(); - size_t numFullBlocks = numClasses / groupSize; - size_t lastBlockSize = numClasses % groupSize; - size_t numBlocks = numFullBlocks + ((lastBlockSize>0)? 1:0); - - // Generate the files with the ::New() calls to each class. These - // are done in groups to keep the translation unit size smaller. - for(unsigned int block=0; block < numBlocks;++block) - { - std::string fileName = this->GenerateCreationFileName(block); - std::string fullName = filePath+"/"+fileName; - - // Generate the output file with copy-if-different. - { - cmGeneratedFileStream fout(fullName.c_str()); - - unsigned int thisBlockSize = - (block < numFullBlocks)? groupSize:lastBlockSize; - - // Actually generate the code in the file. - this->GenerateCreationFile(fout.GetStream(), - block*groupSize, thisBlockSize); - } - - // Add the generated source file into the source list. - cmSourceFile file; - file.SetWrapExclude(true); - file.SetIsAnAbstractClass(false); - file.SetName(fileName.c_str(), filePath.c_str(), - m_Makefile->GetSourceExtensions(), - m_Makefile->GetHeaderExtensions()); - m_Makefile->AddSource(file); - sourceListValue += ";"; - sourceListValue += file.GetSourceName() + ".cxx"; - } - + m_Makefile->AddDefinition(args[1].c_str(), sourceListValue.c_str()); return true; } -std::string -cmVTKMakeInstantiatorCommand::GenerateCreationFileName(unsigned int block) -{ - cmStringStream nameStr; - nameStr << m_ClassName.c_str() << block << ".cxx"; - std::string result = nameStr.str(); - return result; -} - // Generates the class header file with the definition of the class // and its initializer class. void @@ -225,38 +166,28 @@ cmVTKMakeInstantiatorCommand { os << "#include \"" << m_Includes[i].c_str() << "\"\n"; } + + // Write the instantiator class definition. os << - "\n" - "class " << m_ClassName.c_str() << "Initialize;\n" "\n" "class " << m_ExportMacro.c_str() << " " << m_ClassName.c_str() << "\n" "{\n" - " friend class " << m_ClassName.c_str() << "Initialize;\n" - "\n" + "public:\n" + " " << m_ClassName.c_str() << "();\n" + " ~" << m_ClassName.c_str() << "();\n" + "private:\n" " static void ClassInitialize();\n" " static void ClassFinalize();\n" - "\n"; - - for(unsigned int i=0;i < m_Classes.size();++i) - { - os << " static vtkObject* Create_" << m_Classes[i].c_str() << "();\n"; - } - - // Write the initializer class to make sure the creation functions - // get registered when this generated header is included. - os << - "};\n" - "\n" - "class " << m_ExportMacro.c_str() << " " << m_ClassName.c_str() << "Initialize\n" - "{\n" - "public:\n" - " " << m_ClassName.c_str() << "Initialize();\n" - " ~" << m_ClassName.c_str() << "Initialize();\n" - "private:\n" " static unsigned int Count;\n" "};\n" - "\n" - "static " << m_ClassName.c_str() << "Initialize " << m_ClassName.c_str() << "Initializer;\n" + "\n"; + + // Write the initialization instance to make sure the creation + // functions get registered when this generated header is included. + os << + "static " + << m_ClassName.c_str() << " " + << m_ClassName.c_str() << "Initializer;\n" "\n" "#endif\n"; } @@ -268,18 +199,28 @@ void cmVTKMakeInstantiatorCommand ::GenerateImplementationFile(std::ostream& os) { - // Write the ClassInitialize method to register all the creation functions. + // Include the instantiator class header. os << "#include \"" << m_ClassName.c_str() << ".h\"\n" + "\n"; + + // Write the extern declarations for all the creation functions. + for(unsigned int i=0;i < m_Classes.size();++i) + { + os << "extern vtkObject* vtkInstantiator" << m_Classes[i].c_str() << "New();\n"; + } + + // Write the ClassInitialize method to register all the creation functions. + os << "\n" "void " << m_ClassName.c_str() << "::ClassInitialize()\n" "{\n"; - + for(unsigned int i=0;i < m_Classes.size();++i) { os << " vtkInstantiator::RegisterInstantiator(\"" - << m_Classes[i].c_str() << "\", " << m_ClassName.c_str() << "::Create_" - << m_Classes[i].c_str() << ");\n"; + << m_Classes[i].c_str() << "\", vtkInstantiator" + << m_Classes[i].c_str() << "New);\n"; } // Write the ClassFinalize method to unregister all the creation functions. @@ -292,8 +233,8 @@ cmVTKMakeInstantiatorCommand for(unsigned int i=0;i < m_Classes.size();++i) { os << " vtkInstantiator::UnRegisterInstantiator(\"" - << m_Classes[i].c_str() << "\", " << m_ClassName.c_str() << "::Create_" - << m_Classes[i].c_str() << ");\n"; + << m_Classes[i].c_str() << "\", vtkInstantiator" + << m_Classes[i].c_str() << "New);\n"; } // Write the constructor and destructor of the initializer class to @@ -302,50 +243,19 @@ cmVTKMakeInstantiatorCommand os << "}\n" "\n" << - m_ClassName.c_str() << "Initialize::" << m_ClassName.c_str() << "Initialize()\n" + m_ClassName.c_str() << "::" << m_ClassName.c_str() << "()\n" "{\n" - " if(++" << m_ClassName.c_str() << "Initialize::Count == 1)\n" + " if(++" << m_ClassName.c_str() << "::Count == 1)\n" " { " << m_ClassName.c_str() << "::ClassInitialize(); }\n" "}\n" "\n" << - m_ClassName.c_str() << "Initialize::~" << m_ClassName.c_str() << "Initialize()\n" + m_ClassName.c_str() << "::~" << m_ClassName.c_str() << "()\n" "{\n" - " if(--" << m_ClassName.c_str() << "Initialize::Count == 0)\n" + " if(--" << m_ClassName.c_str() << "::Count == 0)\n" " { " << m_ClassName.c_str() << "::ClassFinalize(); }\n" "}\n" "\n" "// Number of translation units that include this class's header.\n" "// Purposely not initialized. Default is static initialization to 0.\n" - "unsigned int " << m_ClassName.c_str() << "Initialize::Count;\n"; -} - -// Generates a file that includes the headers of the classes it knows -// how to create and provides functions which create the classes with -// the New() method. -void -cmVTKMakeInstantiatorCommand -::GenerateCreationFile(std::ostream& os, unsigned int groupStart, - unsigned int groupSize) -{ - // Need to include header of generated class. - os << - "#include \"" << m_ClassName.c_str() << ".h\"\n" - "\n"; - - // Include class files. - for(unsigned int i=0;i < groupSize;++i) - { - os << "#include \"" << m_Classes[groupStart+i].c_str() << ".h\"\n"; - } - - os << - "\n"; - - // Write the create function implementations. - for(unsigned int i=0;i < groupSize;++i) - { - os << "vtkObject* " << m_ClassName.c_str() << "::Create_" - << m_Classes[groupStart+i].c_str() << "() { return " - << m_Classes[groupStart+i].c_str() << "::New(); }\n"; - } + "unsigned int " << m_ClassName.c_str() << "::Count;\n"; } diff --git a/Source/cmVTKMakeInstantiatorCommand.h b/Source/cmVTKMakeInstantiatorCommand.h index ee738ced2..b2678d0b1 100644 --- a/Source/cmVTKMakeInstantiatorCommand.h +++ b/Source/cmVTKMakeInstantiatorCommand.h @@ -69,13 +69,10 @@ public: "The generated class implementation files always go in the build\n" "directory corresponding to the CMakeLists.txt file containing\n" "the command. This is the default location for the header.\n" - "The GROUP_SIZE option must be followed by a positive integer.\n" - "As an implementation detail, the registered creation functions may\n" - "be split up into multiple files. The groupSize option specifies\n" - "the number of classes per file. Its default is 10. The INCLUDES\n" - "option can be followed by a list of zero or more files. These files\n" - "will be #included by the generated instantiator header, and can be\n" - "used to gain access to the specified exportMacro in the C++ code."; + "The INCLUDES option can be followed by a list of zero or more files.\n" + "These files will be #included by the generated instantiator header,\n" + "and can be used to gain access to the specified exportMacro in the\n" + " C++ code."; } cmTypeMacro(cmVTKMakeInstantiatorCommand, cmCommand); @@ -86,12 +83,8 @@ protected: std::vector m_Includes; std::vector m_Classes; - std::string GenerateCreationFileName(unsigned int group); - void GenerateHeaderFile(std::ostream&); void GenerateImplementationFile(std::ostream&); - void GenerateCreationFile(std::ostream&, unsigned int groupStart, - unsigned int groupSize); };