1from shutil import copyfile, rmtree 2from string import Template 3import os.path 4import re 5import sys 6import autogen 7 8class ForwardHeaderGenerator(): 9 def __init__( self, copy, path, includepath, srcpath, project, subprojects, prefix, 10 prefixed, cleanIncludeDir = True, additionalHeaders = {} ): 11 self.copy = copy 12 self.path = path 13 self.includepath = includepath 14 self.srcpath = srcpath 15 self.project = project 16 self.subprojects = subprojects 17 self.prefix = prefix 18 self.prefixed = prefixed 19 self.cleanIncludeDir = cleanIncludeDir 20 self.additionalHeaders = additionalHeaders 21 self.__projectFile = "" 22 23 def run( self ): 24 self.createProject() 25 26 def _isValidHeaderFile( self, filename ): 27 if ( filename.endswith( ".h" ) ): 28 if filename.startswith( "moc_" ): 29 return False 30 if filename.startswith( "ui_" ): 31 return False 32 if filename.startswith( "qrc_" ): 33 return False; 34 if filename.endswith( "_p.h" ): 35 return False 36 return True 37 else: 38 return False 39 40 def _suggestedHeaderNames( self, project, header ): 41 regex = re.compile( "(?:class\s+[{0}|{1}][_0-9A-Z]*_EXPORT|MAKEINCLUDES_EXPORT)\s+([a-zA-Z_][A-Za-z0-9_]*)" 42 .format( project.upper(), self.project.upper() ) ) 43 regex2 = re.compile( "(?:class\s+MAKEINCLUDES_EXPORT)\s+([a-zA-Z_][A-Za-z0-9_]*)" ) 44 regex3 = re.compile( "(?:\\\\file)\s+([a-zA-Z_][A-Za-z0-9_]*)" ) 45 46 f = open( header, "r" ) 47 classNames = set() 48 49 for line in f.readlines(): 50 line = line.strip() 51 52 className = None 53 noPrefix = False 54 if ( regex.match( line ) ): 55 className = regex.match( line ).groups()[0] 56 noPrefix = False 57 else: 58 if regex2.match( line ): 59 className = regex2.match( line ).groups()[0] 60 noPrefix = False 61 else: 62 if ( None != regex3.search( line ) ): 63 className = regex3.search( line ).groups()[0] 64 noPrefix = True 65 66 if not className: 67 continue 68 69 if self.prefixed and not noPrefix: 70 className = project + className 71 72 classNames.add( className ) 73 74 f.close() 75 76 return classNames 77 78 def _addForwardHeader( self, targetPath, fileName, projectFile ): 79 INCLUDE_STR = "#include \"{0}\"" 80 newHeader = open( targetPath, "wb" ) 81 newHeader.write( INCLUDE_STR.format( fileName ) + os.linesep ) 82 newHeader.close() 83 84 basename = os.path.basename( targetPath ) 85 projectFile.write( basename + " \\" + os.linesep ) 86 87 def _createForwardHeader( self, header, projectFile, project ): 88 path = os.path.dirname( header ) 89 basename = os.path.basename( header ) 90 classNames = self._suggestedHeaderNames( project, header ) 91 92 if len( classNames ) > 0: 93 for classname in classNames: 94 fHeaderName = os.path.abspath( path + "/" + classname ) 95 self._addForwardHeader( fHeaderName, basename, projectFile ) 96 97 projectFile.write( basename + " \\" + os.linesep ) 98 elif not basename in self.additionalHeaders.values(): # only create "foo" for "foo.h" if additionalHeaders doesn't overrides it 99 sanitizedBasename = basename.replace( ".h", "" ) 100 101 #fHeaderName = os.path.abspath( self.includepath + "/" + sanitizedBasename ) 102 #self._addForwardHeader( fHeaderName, basename, self.__projectFile ) 103 104 fHeaderNameProjectDir = os.path.dirname( os.path.abspath( header ) ) + "/" + sanitizedBasename; 105 self._addForwardHeader( fHeaderNameProjectDir, "{0}".format( basename ), projectFile ) 106 projectFile.write( basename + " \\" + os.linesep ) 107 108 def createProject( self ): 109 if ( not os.path.exists( self.path ) ): 110 errStr = Template( "Error, the directory $DIR does not exist!" ) 111 errStr = errStr.substitute( DIR = self.path ) 112 raise BaseException( errStr ) 113 114 if self.cleanIncludeDir and os.path.exists( self.includepath ): 115 rmtree( self.includepath ) 116 if not os.path.exists( self.includepath ): 117 os.mkdir( self.includepath ) 118 119 if autogen.policyVersion() >= 2: 120 includeProjectName = os.path.basename( self.includepath.rstrip( "/" ) ) 121 else: 122 includeProjectName = self.project 123 profilename = os.path.abspath( self.includepath ) + "/" + includeProjectName + ".pro" 124 projectFile = open( profilename, "wb" ) 125 self.__projectFile = projectFile 126 lines = [] 127 lines.append( "TEMPLATE = subdirs" + os.linesep ) 128 lines.append( "SUBDIRS = " ) 129 130 for subProject in self.subprojects: 131 line = subProject 132 if ( subProject != self.subprojects[ -1 ] ): 133 line += " \\" 134 lines.append( line + os.linesep ) 135 136 projectFile.writelines( lines ) 137 projectFile.write( os.linesep ) 138 139 projectFile.write( "INSTALL_HEADERS.files = " ) 140 141 for subProject in self.subprojects: 142 self._createSubproject( subProject ) 143 144 for fileName, includePath in self.additionalHeaders.items(): 145 targetPath = os.path.join( self.includepath, fileName ) 146 self._addForwardHeader( targetPath , includePath, projectFile ) 147 148 self._copyHeaders( self.srcpath, self.includepath, projectFile, self.project, self.prefixed ) 149 installPath = "{0}/include".format( self.prefix ) 150 self._projectFile_finalize( projectFile, installPath ) 151 projectFile.close() 152 153 def _createSubproject( self, project ): 154 inclPath = os.path.abspath( self.includepath + "/" + project ) 155 srcPath = os.path.abspath( self.srcpath + "/" + project ) 156 os.mkdir( inclPath ) 157 profilename = os.path.abspath( self.includepath ) + "/" + project + "/" + project + ".pro" 158 projectFile = open( profilename, "wb" ) 159 projectFile.write( "TEMPLATE = subdirs" + os.linesep ) 160 projectFile.write( "INSTALL_HEADERS.files = " ) 161 self._copyHeaders( srcPath, inclPath, projectFile, project, self.prefixed ) 162 installPath = "{0}/include/{1}".format( self.prefix, project ) 163 self._projectFile_finalize( projectFile, installPath ) 164 projectFile.close() 165 166 def _projectFile_finalize( self, projectFile, installPath ): 167 projectFile.write( os.linesep ) 168 #projectFile.write( "message( $$INSTALL_HEADERS.path )" + os.linesep ) 169 projectFile.write( "INSTALL_HEADERS.path = {0}".format( installPath ) + os.linesep ) 170 #projectFile.write( "message( $$INSTALL_HEADERS.path )" + os.linesep ) 171 projectFile.write( "INSTALLS += INSTALL_HEADERS" + os.linesep ) 172 173 def _copyHeaders( self, srcDir, destDir, projectFile, project, prefixed = False ): 174 rootDir = srcDir == self.srcpath 175 dir = os.listdir( srcDir ) 176 headersForCatchAll = [] 177 for filename in dir: 178 if ( rootDir ): 179 if ( filename in self.subprojects ): 180 continue 181 file = os.path.abspath( srcDir + "/" + filename ) 182 if os.path.isdir( file ): 183 self._copyHeaders( file, destDir, projectFile, project, prefixed ) 184 else: 185 if self._isValidHeaderFile( filename ): 186 destfile = os.path.abspath( destDir + "/" + filename ) 187 srcfile = os.path.abspath( srcDir + "/" + filename ) 188 copyfile( srcfile, destfile ) 189 self._createForwardHeader( destfile, projectFile, project ) 190 headersForCatchAll.append( filename ) 191 # Create "catch all" convenience header including all headers: 192 if len( headersForCatchAll ) > 0: 193 catchAllFileName = os.path.abspath( destDir + "/" + os.path.basename( destDir ) ) 194 catchAllContent = ["#include \"%s\"%s" % (header, os.linesep) for header in headersForCatchAll] 195 catchAllFile = open( catchAllFileName, "wb" ) 196 catchAllFile.writelines( catchAllContent ) 197 catchAllFile.close() 198 projectFile.write( os.path.basename( catchAllFileName ) + " \\" + os.linesep ) 199 200