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