Convert build scripts to Python #31
|
@ -3,7 +3,12 @@ import os
|
||||||
import platform
|
import platform
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from utils import pushd, removeall, shellish
|
import checksum
|
||||||
|
from log import *
|
||||||
|
from utils import pushd, removeall
|
||||||
|
|
||||||
|
|
||||||
|
ANGLE_VERSION = "2023-07-05"
|
||||||
|
|
||||||
|
|
||||||
def attach_build_runtime(subparsers):
|
def attach_build_runtime(subparsers):
|
||||||
|
@ -13,24 +18,12 @@ def attach_build_runtime(subparsers):
|
||||||
|
|
||||||
|
|
||||||
def build_runtime(args):
|
def build_runtime(args):
|
||||||
try:
|
ensure_programs()
|
||||||
subprocess.run(["clang", "-v"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
ensure_angle()
|
||||||
except FileNotFoundError:
|
|
||||||
print("ERROR: clang was not found on your system.")
|
|
||||||
if platform.system() == "Windows":
|
|
||||||
print("We recommend installing clang via the Visual Studio installer.")
|
|
||||||
# TODO(ben): Link to the Visual Studio download page (I have no internet right now)
|
|
||||||
elif platform.system() == "Darwin":
|
|
||||||
print("Run the following to install it:")
|
|
||||||
print()
|
|
||||||
print(" brew install llvm")
|
|
||||||
print()
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
# TODO(ben): Check for xcode command line tools
|
|
||||||
|
|
||||||
build_milepost("lib", args.release)
|
build_milepost("lib", args.release)
|
||||||
|
|
||||||
|
|
||||||
def build_milepost(target, release):
|
def build_milepost(target, release):
|
||||||
print("Building milepost...")
|
print("Building milepost...")
|
||||||
with pushd("milepost"):
|
with pushd("milepost"):
|
||||||
|
@ -42,7 +35,8 @@ def build_milepost(target, release):
|
||||||
if platform.system() == "Darwin":
|
if platform.system() == "Darwin":
|
||||||
build_milepost_lib_mac(release)
|
build_milepost_lib_mac(release)
|
||||||
else:
|
else:
|
||||||
print(f"ERROR: can't build milepost for unknown platform '{platform.system()}'")
|
log_error(f"can't build milepost for unknown platform '{platform.system()}'")
|
||||||
|
exit(1)
|
||||||
elif target == "test":
|
elif target == "test":
|
||||||
with pushd("examples/test_app"):
|
with pushd("examples/test_app"):
|
||||||
# TODO?
|
# TODO?
|
||||||
|
@ -50,9 +44,10 @@ def build_milepost(target, release):
|
||||||
elif target == "clean":
|
elif target == "clean":
|
||||||
removeall("bin")
|
removeall("bin")
|
||||||
else:
|
else:
|
||||||
print(f"ERROR: unrecognized milepost target '{target}'")
|
log_error(f"unrecognized milepost target '{target}'")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
|
|
||||||
def build_milepost_lib_mac(release):
|
def build_milepost_lib_mac(release):
|
||||||
sdk_dir = "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk"
|
sdk_dir = "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk"
|
||||||
|
|
||||||
|
@ -123,3 +118,59 @@ def build_milepost_lib_mac(release):
|
||||||
"-id", "@rpath/libmilepost.dylib",
|
"-id", "@rpath/libmilepost.dylib",
|
||||||
"bin/libmilepost.dylib",
|
"bin/libmilepost.dylib",
|
||||||
], check=True)
|
], check=True)
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_programs():
|
||||||
|
try:
|
||||||
|
subprocess.run(["clang", "-v"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||||
|
except FileNotFoundError:
|
||||||
|
msg = log_error("clang was not found on your system.")
|
||||||
|
if platform.system() == "Windows":
|
||||||
|
msg.more("We recommend installing clang via the Visual Studio installer.")
|
||||||
|
# TODO(ben): Link to the Visual Studio download page (I have no internet right now)
|
||||||
|
elif platform.system() == "Darwin":
|
||||||
|
msg.more("Run the following to install it:")
|
||||||
|
msg.more()
|
||||||
|
msg.more(" brew install llvm")
|
||||||
|
msg.more()
|
||||||
|
exit(1)
|
||||||
|
# TODO(ben): Check for xcode command line tools
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_angle():
|
||||||
|
checkfiles = None
|
||||||
|
if platform.system() == "Windows":
|
||||||
|
checkfiles = [
|
||||||
|
["libEGL-win", "milepost/lib/libEGL.dll"],
|
||||||
|
["libGLESv2-win", "milepost/lib/libGLESv2.dll"],
|
||||||
|
]
|
||||||
|
elif platform.system() == "Darwin":
|
||||||
|
# TODO(ben): Do we need specific builds of ANGLE for each macOS version?
|
||||||
|
if platform.machine() == "arm64":
|
||||||
|
checkfiles = [
|
||||||
|
["libEGL-mac-arm64", "milepost/lib/libEGL.dylib"],
|
||||||
|
["libGLESv2-mac-arm64", "milepost/lib/libGLESv2.dylib"],
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
checkfiles = [
|
||||||
|
["libEGL-mac-x64", "milepost/lib/libEGL.dylib"],
|
||||||
|
["libGLESv2-mac-x64", "milepost/lib/libGLESv2.dylib"],
|
||||||
|
]
|
||||||
|
|
||||||
|
if checkfiles is None:
|
||||||
|
log_warning("could not verify if the correct version of ANGLE is present; the build will probably fail.")
|
||||||
|
return
|
||||||
|
|
||||||
|
angle_exists = True
|
||||||
|
for file in checkfiles:
|
||||||
|
key = file[0]
|
||||||
|
filepath = file[1]
|
||||||
|
if not os.path.isfile(filepath):
|
||||||
|
angle_exists = False
|
||||||
|
break
|
||||||
|
if not checksum.checkfile(key, filepath):
|
||||||
|
log_error("wrong version of ANGLE libraries installed")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
if not angle_exists:
|
||||||
|
pass
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
|
||||||
|
from log import *
|
||||||
|
|
||||||
|
|
||||||
|
def checkfile(key, filepath):
|
||||||
|
newsum = filesum(filepath)
|
||||||
|
|
||||||
|
sums = {}
|
||||||
|
with open("scripts/checksums.json", "r") as sumsfile:
|
||||||
|
sums = json.loads(sumsfile.read())
|
||||||
|
if key not in sums:
|
||||||
|
msg = log_warning(f"no checksum saved for {key}")
|
||||||
|
msg.more(f"file had checksum: {newsum}")
|
||||||
|
return False
|
||||||
|
sum = sums[key]
|
||||||
|
|
||||||
|
if sum != newsum:
|
||||||
|
msg = log_warning(f"checksums did not match for {filepath}:")
|
||||||
|
msg.more(f"expected: {sum}")
|
||||||
|
msg.more(f" got: {newsum}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def filesum(filepath):
|
||||||
|
with open(filepath, "rb") as file:
|
||||||
|
return hashlib.sha256(file.read()).hexdigest()
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"libEGL-win": "3c8b22317664650deba704dd40bbd56447c579ee3a3de18a9c114449a883a36d",
|
||||||
|
"libGLESv2-win": "a10e0ce850a981b11d3d0f01a7efbf8ce46ac74e5fa763b5c43a80c4238da389",
|
||||||
|
"libEGL-mac-arm64": "227445d896047207d1dcef91a8182d886692bc470f402033a6f0831eacb82592",
|
||||||
|
"libGLESv2-mac-arm64": "c814948060494796cda4a3febd8652e1bbf0787a69c2f7e9afd41fc666dc91fe"
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
errors = []
|
||||||
|
warnings = []
|
||||||
|
|
||||||
|
|
||||||
|
class Entry:
|
||||||
|
def __init__(self, msg):
|
||||||
|
self.msgs = [msg]
|
||||||
|
|
||||||
|
def more(self, *msgs):
|
||||||
|
if len(msgs) == 0:
|
||||||
|
msgs = [""]
|
||||||
|
for msg in msgs:
|
||||||
|
print(msg)
|
||||||
|
self.msgs.append(msg)
|
||||||
|
|
||||||
|
|
||||||
|
def log_error(msg):
|
||||||
|
msg = f"ERROR: {msg}"
|
||||||
|
print(msg)
|
||||||
|
entry = Entry(msg)
|
||||||
|
errors.append(entry)
|
||||||
|
return entry
|
||||||
|
|
||||||
|
|
||||||
|
def log_warning(msg):
|
||||||
|
msg = f"WARNING: {msg}"
|
||||||
|
print(msg)
|
||||||
|
entry = Entry(msg)
|
||||||
|
warnings.append(entry)
|
||||||
|
return entry
|
||||||
|
|
||||||
|
|
||||||
|
def log_finish():
|
||||||
|
if len(errors) + len(warnings) == 0:
|
||||||
|
print("Task completed successfully.")
|
||||||
|
return
|
||||||
|
|
||||||
|
print()
|
||||||
|
|
||||||
|
errors_str = "1 error" if len(errors) == 1 else f"{len(errors)} errors"
|
||||||
|
warnings_str = "1 warning" if len(warnings) == 1 else f"{len(warnings)} warnings"
|
||||||
|
|
||||||
|
if len(errors) > 0 and len(warnings) > 0:
|
||||||
|
print(f"Task failed with {errors_str} and {warnings_str}:")
|
||||||
|
for entry in warnings:
|
||||||
|
print("\n".join(entry.msgs))
|
||||||
|
for entry in errors:
|
||||||
|
print("\n".join(entry.msgs))
|
||||||
|
elif len(errors) > 0:
|
||||||
|
print(f"Task failed with {errors_str}:")
|
||||||
|
for entry in errors:
|
||||||
|
print("\n".join(entry.msgs))
|
||||||
|
elif len(warnings) > 0:
|
||||||
|
print(f"Task failed with {warnings_str}:")
|
||||||
|
for entry in warnings:
|
||||||
|
print("\n".join(entry.msgs))
|
||||||
|
|
||||||
|
|
||||||
|
def shellish(func):
|
||||||
|
def shellfunc(*args, **kwargs):
|
||||||
|
exitcode = 0
|
||||||
|
try:
|
||||||
|
func(*args, **kwargs)
|
||||||
|
except subprocess.CalledProcessError as err:
|
||||||
|
msg = log_error(f"The following command failed with code {err.returncode}:")
|
||||||
|
msg.more(" ".join(err.cmd))
|
||||||
|
exitcode = err.returncode
|
||||||
|
except SystemExit as err:
|
||||||
|
exitcode = err.code
|
||||||
|
except:
|
||||||
|
log_error(sys.exception())
|
||||||
|
exitcode = 1
|
||||||
|
finally:
|
||||||
|
log_finish()
|
||||||
|
exit(exitcode)
|
||||||
|
return shellfunc
|
|
@ -18,15 +18,3 @@ def pushd(new_dir):
|
||||||
def removeall(dir):
|
def removeall(dir):
|
||||||
[os.remove(f) for f in glob.iglob("{}/*".format(dir), recursive=True)]
|
[os.remove(f) for f in glob.iglob("{}/*".format(dir), recursive=True)]
|
||||||
os.removedirs(dir)
|
os.removedirs(dir)
|
||||||
|
|
||||||
|
|
||||||
def shellish(func):
|
|
||||||
def shellfunc(*args, **kwargs):
|
|
||||||
try:
|
|
||||||
func(*args, **kwargs)
|
|
||||||
except subprocess.CalledProcessError as err:
|
|
||||||
print()
|
|
||||||
print(f"ERROR (code {err.returncode}): The following command failed:")
|
|
||||||
print(" ".join(err.cmd))
|
|
||||||
exit(err.returncode)
|
|
||||||
return shellfunc
|
|
||||||
|
|
Loading…
Reference in New Issue