import argparse import datetime import os import re import sys # Directories to exclude from blob excludedDirs = { "tests", "projects", "doc", "extern" } # Allowed platform suffix per platform # by sorted precedence platformSuffixes = { 'cafe' : ['cafe'], 'durango' : ['durango', 'ms'], 'ios' : ['ios', 'apple'], 'mac' : ['mac', 'apple'], 'orbis' : ['orbis'], 'ps3_ppu' : ['ps3_ppu', 'ps3'], 'ps3_spu' : ['ps3_spu', 'ps3'], 'vita' : ['vita'], 'win32' : ['win32', 'ms_pc', 'ms'], 'win64' : ['win64', 'ms_pc', 'ms'], 'xenon' : ['xenon', 'ms'], 'linux' : ['linux'], 'android' : ['android'] } # Is populated in main knownPlatformSuffixes = {} # The currently generated blob file blobFilenameTemplate = "" # Something that look like 'gear__.cpp' def buildBlobFor(folderToBlob, platform, ext): """ buildBlobFor('path/to/folder', 'win64', 'cpp') """ # Get satellite and module name from argument folderToBlob = folderToBlob.replace('\\', '/') splittedPath = folderToBlob.split('/') satelliteName = splittedPath[0] moduleName = splittedPath[-1] includeName = moduleName # . Add 'gear_' prefix if not already present if moduleName[0:5] != 'gear_': includeName = 'gear_' + moduleName moduleName = moduleName + '_bulk' gearRoot = '../../' # When script is invoked from buildfolder\generation absoluteFolderToBlobDir = gearRoot + folderToBlob global knownPlatformSuffixes knownPlatformSuffixes = set([ item for sublist in platformSuffixes.values() for item in sublist ]) # Nothing to do if folderToBlob is not present if not os.path.exists(absoluteFolderToBlobDir): print 'Info: folder', folderToBlob, 'not found, skipping blob generation' return global blobFilenameTemplate blobFilenameTemplate = moduleName blobFilename = blobFilenameTemplate + '_' + platform + '.' + ext print '* Generating blob:\t', blobFilename oldDir = os.getcwd() os.chdir(absoluteFolderToBlobDir) try: sources = findAllFiles(platform, ext) if not os.path.exists('private'): os.makedirs('private') with open('private/' + blobFilename, 'w') as f: f.write("/* GENERATED FILE. DO NOT EDIT! */\n\n") f.write('#include <' + satelliteName + '/' + includeName + '.h>\n\n') for fname in sources: f.write( '#include <' + folderToBlob + '/' + fname.replace('\\','/') + '>\n' ) finally: os.chdir(oldDir) return None def filterDirs(dirs): """ Remove directories present in the exclusion list """ newDirs = list( set(dirs) - excludedDirs) newDirs.sort() return newDirs def filterFiles(files, platform, ext): """ Filter files based on their extension and platform suffix """ filesSet = set( map( lambda f: f.lower(), files ) ) suffixes = platformSuffixes[platform] def hasHigherPrecedencePlatform(fName,fPlatform): """ Check whether any platform specific suffix of higher precendence is present for this file """ fIndex = suffixes.index(fPlatform) suffixesSubset = suffixes[0:fIndex] suffixesPresent = map(lambda suf: fName+'_'+suf+'.'+ext in filesSet, suffixesSubset) return any(suffixesPresent) def filterFilePredicate(file): fName, fPlatform, fExt = parseFilename(file) if file[0:len(blobFilenameTemplate)] == blobFilenameTemplate: return False if fExt == None or fExt.lower() != ext: return False elif fPlatform == None or suffixes == None: return True else: return (fPlatform in suffixes) and ( not hasHigherPrecedencePlatform(fName, fPlatform) ) return filter( filterFilePredicate, files ) def findAllFiles(platform, ext): """ Example findAllFiles('win64', 'cpp') will find all .cpp in the current folder """ def findAllFiles_internal(path): rootDir, subdirs, rootFiles = os.walk(path).next() subdirs = filterDirs(subdirs) rootFiles = filterFiles(rootFiles, platform, ext) allFiles = [] allFiles += map( lambda f: os.path.normpath(path + '/' + f), rootFiles ) for dir in subdirs: allFiles += findAllFiles_internal(os.path.normpath(path + '/' + dir)) return allFiles return findAllFiles_internal('.') def parseFilename(fileName): """ Returns None if file has no extension else returns (file,platform,extension) """ rex = r'(.*?)(_(\w+))?(\.(\w+))?$' m = re.search( rex, fileName, flags = re.IGNORECASE ) if m: if m.group(3) in knownPlatformSuffixes: m = m.group(1), m.group(3), m.group(5) elif m.group(3): m = m.group(1) + m.group(2), None, m.group(5) else: m = m.group(1), None, m.group(5) return m