mirror of
https://github.com/elliotnunn/BuildCubeE.git
synced 2025-03-02 17:29:03 +00:00
wip
This commit is contained in:
parent
fd1ce45b9b
commit
9da3ab878f
243
BuildCubeE.py
243
BuildCubeE.py
@ -1,3 +1,244 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
print('there, done!')
|
||||
import argparse
|
||||
import os
|
||||
import os.path as path
|
||||
import tempfile
|
||||
import datetime as dt
|
||||
import time
|
||||
import subprocess as sp
|
||||
import shutil
|
||||
import re
|
||||
|
||||
########################################################################
|
||||
# Logs
|
||||
|
||||
curstage = 0
|
||||
NSTAGES = 7
|
||||
|
||||
def nextstage(name):
|
||||
global curstage
|
||||
curstage += 1
|
||||
print('[CubeE build %d/%d] %s' % (curstage, NSTAGES, name))
|
||||
|
||||
########################################################################
|
||||
# Argparse
|
||||
|
||||
args = argparse.ArgumentParser()
|
||||
args.add_argument('-v --verbose', action='store_true', help='List every file rather than summaries')
|
||||
args = args.parse_args()
|
||||
args.maker = 'RISC'
|
||||
|
||||
########################################################################
|
||||
|
||||
nextstage('Walking source tree')
|
||||
|
||||
def includefilter(n):
|
||||
if n.startswith('.'): return False
|
||||
if n.upper().endswith('.DMG'): return False
|
||||
return True
|
||||
|
||||
g_filetree = []
|
||||
g_reztree = []
|
||||
for dirpath, dirnames, filenames in os.walk('.'):
|
||||
dirnames[:] = list(filter(includefilter, dirnames))
|
||||
filenames[:] = list(filter(includefilter, filenames))
|
||||
for f in filenames:
|
||||
p = path.join(dirpath, f).lstrip('./')
|
||||
if p.endswith('.RezDump'):
|
||||
g_reztree.append(p)
|
||||
p = p.rpartition('.')[0]
|
||||
g_filetree.append(p)
|
||||
g_filetree = sorted(set(g_filetree))
|
||||
|
||||
print('Got %d files' % len(g_filetree))
|
||||
|
||||
########################################################################
|
||||
|
||||
nextstage('Classifying files')
|
||||
|
||||
g_fileclass = {}
|
||||
for f in g_filetree:
|
||||
ext = os.path.splitext(f)[1].lower()
|
||||
if ext in ['.o', '.lib']:
|
||||
inf = 'MPS OBJ '
|
||||
elif ext in ['.txt', '.a', '.c']:
|
||||
inf = 'MPS TEXT'
|
||||
elif f.startswith('Tools/'):
|
||||
inf = 'MPS MPST'
|
||||
else:
|
||||
inf = 'MPS TEXT'
|
||||
g_fileclass[f] = inf
|
||||
|
||||
########################################################################
|
||||
|
||||
nextstage('Dating files')
|
||||
|
||||
def trytime(p):
|
||||
t = []
|
||||
try:
|
||||
t.append(path.getmtime(p))
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
try:
|
||||
t.append(path.getmtime(p + '.RezDump'))
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
return max(t)
|
||||
|
||||
def datefiles(files):
|
||||
tsbase = time.mktime(dt.date(1993, 12, 20).timetuple())
|
||||
|
||||
f2ts = {f: trytime(f) for f in files}
|
||||
idx2ts = enumerate(sorted(set(f2ts.values())))
|
||||
ts2idx = {ts: idx for (idx, ts) in idx2ts}
|
||||
return {f: tsbase + 60*ts2idx[ts] for (f, ts) in f2ts.items()}
|
||||
|
||||
g_filetime = datefiles(g_filetree)
|
||||
|
||||
########################################################################
|
||||
|
||||
nextstage('Copying to the build tree')
|
||||
|
||||
g_tmp = tempfile.TemporaryDirectory()
|
||||
g_tmp.name = '/tmp/elmo'; os.system('rm -rf /tmp/elmo'); os.system('mkdir /tmp/elmo')
|
||||
|
||||
for f in g_reztree:
|
||||
d = path.dirname(f)
|
||||
if d: os.makedirs(path.join(g_tmp.name, d), exist_ok=True)
|
||||
|
||||
newf = f.rpartition('.')[0]
|
||||
sp.run(['Rez', '-o', path.join(g_tmp.name, newf), f])
|
||||
|
||||
setfile_batch = {}
|
||||
for f in g_filetree:
|
||||
d = path.dirname(f)
|
||||
if d: os.makedirs(path.join(g_tmp.name, d), exist_ok=True)
|
||||
|
||||
fclass = g_fileclass[f]
|
||||
ftime = g_filetime[f]
|
||||
|
||||
try:
|
||||
with open(f, 'rb') as fd:
|
||||
data = fd.read()
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
else:
|
||||
if 'TEXT' in fclass:
|
||||
data = data.replace(b'\n', b'\r')
|
||||
|
||||
opath = path.join(g_tmp.name, f)
|
||||
with open(opath, 'wb') as fd:
|
||||
fd.write(data)
|
||||
|
||||
os.utime(opath, (ftime, ftime))
|
||||
|
||||
if fclass not in setfile_batch: setfile_batch[fclass] = []
|
||||
setfile_batch[fclass].append(f)
|
||||
|
||||
for fclass, flist in setfile_batch.items():
|
||||
sp.run(['SetFile', '-c', fclass[:4], '-t', fclass[4:], *flist], cwd=g_tmp.name)
|
||||
|
||||
########################################################################
|
||||
|
||||
nextstage('Creating BuildResults')
|
||||
|
||||
for dname in ['Image', 'Lib', 'Obj', 'Rsrc', 'Text']:
|
||||
os.makedirs(path.join(g_tmp.name, 'BuildResults', args.maker, dname), exist_ok=True)
|
||||
|
||||
########################################################################
|
||||
|
||||
nextstage('Splicing amphibian DNA into makefiles')
|
||||
|
||||
OVERDIR = 'Amphibian'
|
||||
|
||||
try:
|
||||
overs = os.listdir(path.join(g_tmp.name, OVERDIR))
|
||||
if not overs: raise FileNotFoundError
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
else:
|
||||
overs_re = '|'.join(re.escape(x) for x in overs)
|
||||
overs_re = rb'^[^#\s]*\b(Thing.lib)"?\s*\xC4\s*'.replace(b'Thing.lib', overs_re.encode('ascii'))
|
||||
overs_re = re.compile(overs_re, re.IGNORECASE)
|
||||
|
||||
failed = list(overs)
|
||||
|
||||
for f in g_filetree:
|
||||
if not f.upper().endswith('.MAKE'): continue
|
||||
with open(path.join(g_tmp.name, f), 'rb') as fd:
|
||||
mfile = fd.read().split(b'\r')
|
||||
|
||||
havechanged = False
|
||||
newmfile = []
|
||||
|
||||
idx = -1
|
||||
while idx + 1 < len(mfile):
|
||||
idx += 1
|
||||
m = overs_re.match(mfile[idx])
|
||||
if m:
|
||||
thefile = m.group(1)
|
||||
havechanged = True
|
||||
newmfile.append(b'# Rule replaced at build time by ' + path.basename(__file__).encode('ascii'))
|
||||
failed = [x for x in failed if x.upper() != thefile.decode('ascii').upper()]
|
||||
|
||||
srcfile = b'{Sources}%s:%s' % (OVERDIR.encode('ascii'), thefile)
|
||||
newmfile.append(m.group(0) + srcfile)
|
||||
newmfile.append(b'\tDuplicate -y {Deps} {Targ}')
|
||||
|
||||
lastidx = idx # how many "old" lines should be commented out?
|
||||
if mfile[idx].endswith(b'\xB6'):
|
||||
while lastidx + 1 < len(mfile) and mfile[lastidx + 1].endswith(b'\xB6'):
|
||||
lastidx += 1 # capture continuations of first line
|
||||
while lastidx + 1 < len(mfile) and mfile[lastidx + 1].startswith(b'\t'):
|
||||
lastidx += 1 # capture build lines starting with tab
|
||||
|
||||
while idx <= lastidx:
|
||||
newmfile.append(b'#\t' + mfile[idx])
|
||||
idx += 1
|
||||
else:
|
||||
newmfile.append(mfile[idx])
|
||||
|
||||
if havechanged:
|
||||
with open(path.join(g_tmp.name, f), 'wb') as fd:
|
||||
fd.write(b'\r'.join(newmfile))
|
||||
|
||||
if failed: # try to find where these override files with *no build rule* should go
|
||||
found_locations = {k: [] for k in failed}
|
||||
|
||||
overs_re = '|'.join(re.escape(x) for x in failed)
|
||||
overs_re = rb'^[^#]*"({\w+}(?:\w+:)*)(Thing.lib)"'.replace(b'Thing.lib', overs_re.encode('ascii'))
|
||||
overs_re = re.compile(overs_re, re.IGNORECASE)
|
||||
|
||||
for f in g_filetree:
|
||||
if not f.upper().endswith('.MAKE'): continue
|
||||
with open(path.join(g_tmp.name, f), 'rb') as fd:
|
||||
mfile = fd.read().split(b'\r')
|
||||
|
||||
for line in mfile:
|
||||
m = overs_re.match(line)
|
||||
if m:
|
||||
orig_name = next(x for x in failed if x.upper() == m.group(2).decode('ascii').upper())
|
||||
found_loc = m.group(1)+m.group(2)
|
||||
if found_loc.upper() not in (x.upper() for x in found_locations[orig_name]):
|
||||
found_locations[orig_name].append(found_loc)
|
||||
|
||||
with open(path.join(g_tmp.name, 'Make', 'RISC.make'), 'ab') as fd:
|
||||
fd.write(b'\r# Rules created at build time by %s\r' % path.basename(__file__).encode('ascii'))
|
||||
for orig_name, found_locs in found_locations.items():
|
||||
if len(found_locs) == 1:
|
||||
failed = [x for x in failed if x != orig_name]
|
||||
fd.write(found_locs[0])
|
||||
fd.write(b' \xC4 {Sources}%s:%s\r' % (OVERDIR.encode('ascii'), orig_name.encode('ascii')))
|
||||
fd.write(b'\tDuplicate -y {Deps} {Targ}\r')
|
||||
|
||||
print('Successfully edited: %d; Failed: %s' % (len(overs) - len(failed), ' '.join(failed) or 'none'))
|
||||
|
||||
########################################################################
|
||||
|
||||
nextstage('Running Make')
|
||||
|
||||
sp.run(['mpw', 'Make', '-f', ':Make:RISC.make', '-d', 'Sources=:'], cwd=g_tmp.name)
|
||||
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user