135 lines
4.4 KiB
Python
135 lines
4.4 KiB
Python
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
|
|
|
|
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:
|
|
os.makedirs(os.path.dirname(filename), exist_ok=True)
|
|
self.out = open(filename, "w")
|
|
self.filename = None
|
|
def close(self):
|
|
if self.out.closed:
|
|
return
|
|
if self.filename:
|
|
with open(self.filename) as handle:
|
|
oldcontents = handle.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', 'tsc', 'tse']:
|
|
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 sorted(shaderfiles):
|
|
shaderfile = os.path.join(shaderdir, filename)
|
|
if not os.path.exists(shaderfile):
|
|
shaderfile = os.path.join(shaderdir2, filename)
|
|
|
|
with open(shaderfile, 'r') 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 = ''
|
|
|
|
with openw(os.path.join(outputdir, 'PyMOLBuildInfo.h')) as out:
|
|
print('''
|
|
#define _PyMOL_BUILD_DATE %d
|
|
#define _PYMOL_BUILD_GIT_SHA "%s"
|
|
''' % (time.time(), sha), file=out)
|
|
|
|
if __name__ == "__main__":
|
|
create_shadertext(*sys.argv[1:6])
|
|
create_buildinfo(dirname(sys.argv[4]), dirname(dirname(sys.argv[1])))
|