1from __future__ import print_function 2 3try: 4 import cStringIO 5except ImportError: 6 import io as cStringIO 7 8import sys, os 9import time 10import re 11import glob 12from collections import defaultdict 13from os.path import dirname 14from subprocess import Popen, PIPE 15from distutils import dir_util 16 17def create_all(generated_dir, pymoldir="."): 18 ''' 19 Generate various stuff 20 ''' 21 create_shadertext( 22 os.path.join(pymoldir, "data", "shaders"), 23 generated_dir, 24 os.path.join(generated_dir, "ShaderText.h"), 25 os.path.join(generated_dir, "ShaderText.cpp")) 26 create_buildinfo(generated_dir, pymoldir) 27 28class openw(object): 29 """ 30 File-like object for writing files. File is actually only 31 written if the content changed. 32 """ 33 def __init__(self, filename): 34 if os.path.exists(filename): 35 self.out = cStringIO.StringIO() 36 self.filename = filename 37 else: 38 dir_util.mkpath(os.path.dirname(filename)) 39 self.out = open(filename, "w") 40 self.filename = None 41 def close(self): 42 if self.out.closed: 43 return 44 if self.filename: 45 with open(self.filename) as handle: 46 oldcontents = handle.read() 47 newcontents = self.out.getvalue() 48 if oldcontents != newcontents: 49 self.out = open(self.filename, "w") 50 self.out.write(newcontents) 51 self.out.close() 52 def __getattr__(self, name): 53 return getattr(self.out, name) 54 def __enter__(self): 55 return self 56 def __exit__(self, *a, **k): 57 self.close() 58 def __del__(self): 59 self.close() 60 61def create_shadertext(shaderdir, shaderdir2, outputheader, outputfile): 62 63 outputheader = openw(outputheader) 64 outputfile = openw(outputfile) 65 66 include_deps = defaultdict(set) 67 ifdef_deps = defaultdict(set) 68 69 # get all *.gs *.vs *.fs *.shared from the two input directories 70 shaderfiles = set() 71 for sdir in [shaderdir, shaderdir2]: 72 for ext in ['gs', 'vs', 'fs', 'shared']: 73 shaderfiles.update(map(os.path.basename, 74 sorted(glob.glob(os.path.join(sdir, '*.' + ext))))) 75 76 varname = '_shader_cache_raw' 77 outputheader.write('extern const char * %s[];\n' % varname) 78 outputfile.write('const char * %s[] = {\n' % varname) 79 80 for filename in sorted(shaderfiles): 81 shaderfile = os.path.join(shaderdir, filename) 82 if not os.path.exists(shaderfile): 83 shaderfile = os.path.join(shaderdir2, filename) 84 85 with open(shaderfile, 'r') as handle: 86 contents = handle.read() 87 88 if True: 89 outputfile.write('"%s", ""\n' % (filename)) 90 91 for line in contents.splitlines(): 92 line = line.strip() 93 94 # skip blank lines and obvious comments 95 if not line or line.startswith('//') and not '*/' in line: 96 continue 97 98 # write line, quoted, escaped and with a line feed 99 outputfile.write("\"%s\\n\"\n" % line.replace('\\', '\\\\').replace('"', r'\"')) 100 101 # include and ifdef dependencies 102 if line.startswith('#include'): 103 include_deps[line.split()[1]].add(filename) 104 elif line.startswith('#ifdef') or line.startswith('#ifndef'): 105 ifdef_deps[line.split()[1]].add(filename) 106 107 outputfile.write(',\n') 108 109 outputfile.write('0};\n') 110 111 # include and ifdef dependencies 112 for varname, deps in [ 113 ('_include_deps', include_deps), 114 ('_ifdef_deps', ifdef_deps)]: 115 outputheader.write('extern const char * %s[];\n' % varname) 116 outputfile.write('const char * %s[] = {\n' % varname) 117 for name, itemdeps in deps.items(): 118 outputfile.write('"%s", "%s", 0,\n' % (name, '", "'.join(sorted(itemdeps)))) 119 outputfile.write('0};\n') 120 121 outputheader.close() 122 outputfile.close() 123 124def create_buildinfo(outputdir, pymoldir='.'): 125 126 try: 127 sha = Popen(['git', 'rev-parse', 'HEAD'], cwd=pymoldir, 128 stdout=PIPE).stdout.read().strip().decode() 129 except OSError: 130 sha = '' 131 132 with openw(os.path.join(outputdir, 'PyMOLBuildInfo.h')) as out: 133 print(''' 134#define _PyMOL_BUILD_DATE %d 135#define _PYMOL_BUILD_GIT_SHA "%s" 136 ''' % (time.time(), sha), file=out) 137 138if __name__ == "__main__": 139 create_shadertext(*sys.argv[1:6]) 140 create_buildinfo(dirname(sys.argv[4]), dirname(dirname(sys.argv[1]))) 141