mirror of
https://github.com/encounter/ac-decomp.git
synced 2026-03-30 10:57:04 -07:00
107 lines
4.0 KiB
Python
107 lines
4.0 KiB
Python
import subprocess
|
|
import sys
|
|
import os
|
|
import hashlib
|
|
import argparse
|
|
import common as c
|
|
|
|
# List of Ninja build targets
|
|
NINJA_BUILD_TARGETS = [ ['src/data/bin1', 'out/forest_1st.arc', 'dump/forest_1st.arc'], ['src/data/bin2', 'out/forest_2nd.arc', 'dump/forest_2nd.arc'] ]
|
|
|
|
def calculate_directory_hash(path, hash_func):
|
|
if not os.path.isdir(path):
|
|
raise NotADirectoryError(f"{path} is not a directory")
|
|
|
|
hasher = hash_func()
|
|
for root, dirs, files in os.walk(path):
|
|
for names in files:
|
|
filepath = os.path.join(root, names)
|
|
try:
|
|
with open(filepath, 'rb') as f:
|
|
while True:
|
|
data = f.read(65536) # Read in chunks to handle large files
|
|
if not data:
|
|
break
|
|
hasher.update(data)
|
|
except IOError:
|
|
# Handle errors as needed
|
|
pass
|
|
return hasher.hexdigest()
|
|
|
|
def directory_changed(path, build_dir, hash_func=hashlib.md5):
|
|
hash_file = os.path.join(build_dir, f'{os.path.basename(os.path.normpath(path))}.dirhash')
|
|
current_hash = calculate_directory_hash(path, hash_func)
|
|
try:
|
|
with open(hash_file, 'r') as f:
|
|
stored_hash = f.read()
|
|
except FileNotFoundError:
|
|
stored_hash = None
|
|
|
|
if current_hash != stored_hash:
|
|
os.makedirs(build_dir, exist_ok=True)
|
|
with open(hash_file, 'w') as f:
|
|
f.write(current_hash)
|
|
return True
|
|
return False
|
|
|
|
def run_ninja_build(target):
|
|
try:
|
|
subprocess.run(['ninja', '-v', target], check=True)
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"Error running Ninja build for target {target}: {e}")
|
|
sys.exit(1)
|
|
|
|
def check_and_dump_arc(target, dump, verbose=False):
|
|
if not os.path.exists(target):
|
|
assert os.path.exists(dump), f"Please add missing file: {dump}"
|
|
print(f'Dumping {dump}')
|
|
|
|
try:
|
|
if verbose:
|
|
subprocess.run(['python3', 'tools/arc_tool.py', dump, os.path.dirname(target)])
|
|
else:
|
|
subprocess.run(['python3', 'tools/arc_tool.py', '-v', dump, os.path.dirname(target)])
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"Error running arc_tool")
|
|
sys.exit(1)
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser(description='Build Animal Crossing')
|
|
parser.add_argument('--clean', help='Cleans all build artifacts', required=False, action='store_true')
|
|
parser.add_argument('-v', help='Enable verbose logging', required=False, action='store_true')
|
|
|
|
args = parser.parse_args()
|
|
|
|
if args.clean:
|
|
for target in NINJA_BUILD_TARGETS:
|
|
rel_path = f'{os.path.basename(os.path.normpath(target[0]))}.dirhash'
|
|
path = os.path.join('build', rel_path)
|
|
if os.path.exists(path):
|
|
os.remove(path)
|
|
try:
|
|
subprocess.run(['ninja', '-t', 'clean'], check=True)
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"Error running ninja -t clean")
|
|
sys.exit(1)
|
|
else:
|
|
for target in NINJA_BUILD_TARGETS:
|
|
check_and_dump_arc(target[0], target[2], args.v)
|
|
if directory_changed(target[0], 'build'):
|
|
if os.path.exists(target[1]):
|
|
os.remove(target[1])
|
|
run_ninja_build(target[1])
|
|
else:
|
|
print(f"No changes in {target[0]}, skipping build.")
|
|
try:
|
|
if args.v:
|
|
subprocess.run(['ninja', '-v'], check=True)
|
|
else:
|
|
subprocess.run(['ninja'], check=True)
|
|
# Compress foresta.rel
|
|
if os.path.exists(c.REL_OUT):
|
|
print("Compressing foresta.rel to foresta.rel.szs")
|
|
subprocess.call([f'./{c.ORTHRUS}', 'ncompress', 'yaz0', '-c', c.REL_OUT, c.REL_SZS_OUT])
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"Error running Ninja build")
|
|
sys.exit(1)
|