summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/cmCommands.cxx4
-rw-r--r--Source/cmVTKMakeInstantiatorCommand.cxx343
-rw-r--r--Source/cmVTKMakeInstantiatorCommand.h117
3 files changed, 462 insertions, 2 deletions
diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx
index 8752159..0556326 100644
--- a/Source/cmCommands.cxx
+++ b/Source/cmCommands.cxx
@@ -64,6 +64,7 @@
#include "cmQTWrapUICommand.cxx"
#include "cmWrapExcludeFilesCommand.cxx"
#include "cmAddCustomCommandCommand.cxx"
+#include "cmVTKMakeInstantiatorCommand.cxx"
void GetPredefinedCommands(std::list<cmCommand*>& commands)
{
@@ -128,6 +129,5 @@ void GetPredefinedCommands(std::list<cmCommand*>& commands)
commands.push_back(new cmQTWrapUICommand);
commands.push_back(new cmWrapExcludeFilesCommand);
commands.push_back(new cmAddCustomCommandCommand);
+ commands.push_back(new cmVTKMakeInstantiatorCommand);
}
-
-
diff --git a/Source/cmVTKMakeInstantiatorCommand.cxx b/Source/cmVTKMakeInstantiatorCommand.cxx
new file mode 100644
index 0000000..b445b53
--- /dev/null
+++ b/Source/cmVTKMakeInstantiatorCommand.cxx
@@ -0,0 +1,343 @@
+/*=========================================================================
+
+ Program: Insight Segmentation & Registration Toolkit
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+Copyright (c) 2001 Insight Consortium
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * The name of the Insight Consortium, nor the names of any consortium members,
+ nor of any contributors, may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ * Modified source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=========================================================================*/
+#include "cmVTKMakeInstantiatorCommand.h"
+#include "cmCacheManager.h"
+#include "cmGeneratedFileStream.h"
+
+bool
+cmVTKMakeInstantiatorCommand
+::InitialPass(std::vector<std::string> const& args)
+{
+ if(args.size() < 3)
+ {
+ this->SetError("called with incorrect number of arguments");
+ return false;
+ }
+
+ std::string libName = args[0];
+ std::string srcListName = args[1];
+ m_ExportMacro = args[2];
+ unsigned int groupSize = 10;
+
+ // Find the path of the files to be generated.
+ std::string filePath = m_Makefile->GetCurrentOutputDirectory();
+ std::string headerPath = filePath;
+
+ if(args.size() > 3)
+ {
+ for(unsigned int i=3;i < args.size();++i)
+ {
+ if(args[i] == "GROUP_SIZE")
+ {
+ 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(++i < args.size())
+ {
+ headerPath = args[i];
+ m_Makefile->ExpandVariablesInString(headerPath);
+ }
+ else
+ {
+ this->SetError("HEADER_LOCATION option used without value.");
+ return false;
+ }
+ }
+ }
+ }
+
+ m_Makefile->ExpandVariablesInString(srcListName);
+
+ // Find the source list specified.
+ cmMakefile::SourceMap::iterator srcListIter =
+ m_Makefile->GetSources().find(srcListName);
+
+ if(srcListIter == m_Makefile->GetSources().end())
+ {
+ std::string errStr = "No source list named " + srcListName;
+ this->SetError(errStr.c_str());
+ return false;
+ }
+
+ m_ClassName = libName+"Instantiator";
+
+ std::vector<cmSourceFile>& srcList = srcListIter->second;
+
+ // Collect the names of the classes.
+ for(std::vector<cmSourceFile>::iterator src = srcList.begin();
+ src != srcList.end();++src)
+ {
+ // Wrap-excluded and abstract classes do not have a New() method.
+ // vtkIndent and vtkTimeStamp are special cases and are not
+ // vtkObject subclasses.
+ if(!src->GetWrapExclude() && !src->GetIsAnAbstractClass()
+ && (src->GetSourceName() != "vtkIndent")
+ && (src->GetSourceName() != "vtkTimeStamp"))
+ {
+ m_Classes.push_back(src->GetSourceName());
+ }
+ }
+
+ // Generate the header with the class declaration.
+ {
+ std::string fileName = m_ClassName + ".h";
+ std::string fullName = headerPath+"/"+fileName;
+
+ // Generate the output file with copy-if-different.
+ cmGeneratedFileStream fout(fullName.c_str());
+
+ // Actually generate the code in the file.
+ this->GenerateHeaderFile(fout.GetStream());
+ }
+
+ // Generate the implementation file.
+ {
+ std::string fileName = m_ClassName + ".cxx";
+ std::string fullName = filePath+"/"+fileName;
+
+ // Generate the output file with copy-if-different.
+ {
+ cmGeneratedFileStream fout(fullName.c_str());
+
+ // Actually generate the code in the file.
+ this->GenerateImplementationFile(fout.GetStream());
+ }
+
+ // 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, srcListName.c_str());
+ }
+
+ unsigned int numClasses = m_Classes.size();
+ unsigned int numFullBlocks = numClasses / groupSize;
+ unsigned int lastBlockSize = numClasses % groupSize;
+ unsigned int 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, srcListName.c_str());
+ }
+
+ return true;
+}
+
+std::string
+cmVTKMakeInstantiatorCommand::GenerateCreationFileName(unsigned int block)
+{
+ std::ostrstream nameStr;
+ nameStr << m_ClassName.c_str() << block << ".cxx" << std::ends;
+ std::string result = nameStr.str();
+ nameStr.rdbuf()->freeze(0);
+ return result;
+}
+
+// Generates the class header file with the definition of the class
+// and its initializer class.
+void
+cmVTKMakeInstantiatorCommand
+::GenerateHeaderFile(std::ostream& os)
+{
+ os <<
+ "#ifndef __" << m_ClassName.c_str() << "_h\n"
+ "#define __" << m_ClassName.c_str() << "_h\n"
+ "\n"
+ "#include \"vtkInstantiator.h\"\n"
+ "\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"
+ " 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"
+ "#endif\n";
+}
+
+// Generates the file with the implementation of the class. All
+// methods except the actual object creation functions are generated
+// here.
+void
+cmVTKMakeInstantiatorCommand
+::GenerateImplementationFile(std::ostream& os)
+{
+ // Write the ClassInitialize method to register all the creation functions.
+ os <<
+ "#include \"" << m_ClassName.c_str() << ".h\"\n"
+ "\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";
+ }
+
+ // Write the ClassFinalize method to unregister all the creation functions.
+ os <<
+ "}\n"
+ "\n"
+ "void " << m_ClassName.c_str() << "::ClassFinalize()\n"
+ "{\n";
+
+ 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";
+ }
+
+ // Write the constructor and destructor of the initializer class to
+ // call the ClassInitialize and ClassFinalize methods at the right
+ // time.
+ os <<
+ "}\n"
+ "\n" <<
+ m_ClassName.c_str() << "Initialize::" << m_ClassName.c_str() << "Initialize()\n"
+ "{\n"
+ " if(++" << m_ClassName.c_str() << "Initialize::Count == 1)\n"
+ " { " << m_ClassName.c_str() << "::ClassInitialize(); }\n"
+ "}\n"
+ "\n" <<
+ m_ClassName.c_str() << "Initialize::~" << m_ClassName.c_str() << "Initialize()\n"
+ "{\n"
+ " if(--" << m_ClassName.c_str() << "Initialize::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";
+ }
+}
diff --git a/Source/cmVTKMakeInstantiatorCommand.h b/Source/cmVTKMakeInstantiatorCommand.h
new file mode 100644
index 0000000..a475312
--- /dev/null
+++ b/Source/cmVTKMakeInstantiatorCommand.h
@@ -0,0 +1,117 @@
+/*=========================================================================
+
+ Program: Insight Segmentation & Registration Toolkit
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+Copyright (c) 2001 Insight Consortium
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * The name of the Insight Consortium, nor the names of any consortium members,
+ nor of any contributors, may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ * Modified source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=========================================================================*/
+#ifndef cmVTKMakeInstantiatorCommand_h
+#define cmVTKMakeInstantiatorCommand_h
+
+#include "cmStandardIncludes.h"
+#include "cmCommand.h"
+
+/** \class cmVTKMakeInstantiatorCommand
+ * cmVTKMakeInstantiatorCommand implements the VTK_MAKE_INSTANTIATOR
+ * command. This generates a source file to add to a VTK library that
+ * registers instance creation functions with vtkInstantiator for every
+ * class in that library.
+ */
+class cmVTKMakeInstantiatorCommand : public cmCommand
+{
+public:
+ /** This is a virtual constructor for the command. */
+ virtual cmCommand* Clone()
+ { return new cmVTKMakeInstantiatorCommand; }
+
+ /**
+ * This is called when the command is first encountered in
+ * the CMakeLists.txt file.
+ */
+ virtual bool InitialPass(std::vector<std::string> const& args);
+
+ /** The name of the command as specified in CMakeList.txt. */
+ virtual const char* GetName() { return "VTK_MAKE_INSTANTIATOR"; }
+
+ /** Succinct documentation. */
+ virtual const char* GetTerseDocumentation()
+ {
+ return "Setup a library's classes to be created by vtkInstantiator";
+ }
+
+ /** More documentation. */
+ virtual const char* GetFullDocumentation()
+ {
+ return
+ "VTK_MAKE_INSTANTIATOR(libName srcList exportMacro\n"
+ " [HEADER_LOCATION dir] [GROUP_SIZE groupSize])\n"
+ "Generates a new class for the given library to allow its other\n"
+ "classes to be created by vtkInstantiator. Functions to create\n"
+ "classes listed in srcList are registered with vtkInstantiator, and\n"
+ "the new class containing this code is added to the srcList for\n"
+ "inclusion in the library. The libName argument is used to generate\n"
+ "the filename and name of the class used to register the functions\n"
+ "when the library is loaded. The exportMacro is the name of the\n"
+ "DLL export macro to use in the class definition\n"
+ "(ex. VTK_COMMON_EXPORT).\n"
+ "The HEADER_LOCATION option must be followed by a path. It specifies\n"
+ "the directory in which to place the generated class's header file.\n"
+ "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.";
+ }
+
+ cmTypeMacro(cmVTKMakeInstantiatorCommand, cmCommand);
+
+protected:
+ std::string m_ClassName;
+ std::string m_ExportMacro;
+ std::vector<cmStdString> 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);
+};
+
+
+#endif