erythros/scripts/build-all
Alec Murphy a322c06850 Everywhere: Give stbtt its own 32MB static memory pool
At boot time, we preallocate 32MB of RAM to reuse for all malloc()
requests by stbtt_RenderText(), which should be more than enough for the
primary use case (browsing web pages).
2025-04-19 21:01:14 -04:00

269 lines
No EOL
13 KiB
Python
Executable file

#!/usr/bin/python3
from pathlib import Path
import glob
import json
import os
import subprocess
import sys
import time
if len(sys.argv) < 2:
raise ValueError('wrong number of arguments')
home_path = str(Path.home()) + '/'
project_path = sys.argv[1] + '/'
project_name = project_path.rsplit('/')[-2]
build_options_file = project_path + 'build_options.json'
try:
build_options = json.loads(open(build_options_file, "rb").read())
except:
build_options = {}
# Default settings
default_settings = {
'isoc_file': project_path + 'build/isoc/Erythros.ISO.C',
'redsea_path': project_path + 'build/redsea',
'jakt_compiler_path': home_path + 'cloned/jakt/build/bin/jakt',
'jakt_runtime_path': home_path + 'cloned/jakt/runtime',
'jakt_lib_path': home_path + 'cloned/jakt/build/lib/x86_64-unknown-linux-unknown/',
'qemu_bin_path': 'qemu-system-x86_64',
'qemu_slipstream_iso_file': project_path + 'build/isoc/bootable.iso',
'qemu_virtio_disk_path': home_path + 'erythros-virtio-disk.qcow2',
'templeos_iso_file': home_path + 'iso/TempleOS.ISO'
}
isoc_file = build_options['isoc_file'] if 'isoc_file' in build_options else default_settings['isoc_file']
redsea_path = build_options['redsea_path'] if 'redsea_path' in build_options else default_settings['redsea_path']
jakt_compiler_path = build_options['jakt_compiler_path'] if 'jakt_compiler_path' in build_options else default_settings['jakt_compiler_path']
jakt_runtime_path = build_options['jakt_runtime_path'] if 'jakt_runtime_path' in build_options else default_settings['jakt_runtime_path']
jakt_lib_path = build_options['jakt_lib_path'] if 'jakt_lib_path' in build_options else default_settings['jakt_lib_path']
qemu_bin_path = build_options['qemu_bin_path'] if 'qemu_bin_path' in build_options else default_settings['qemu_bin_path']
qemu_slipstream_iso_file = build_options['qemu_slipstream_iso_file'] if 'qemu_slipstream_iso_file' in build_options else default_settings['qemu_slipstream_iso_file']
qemu_virtio_disk_path = build_options['qemu_virtio_disk_path'] if 'qemu_virtio_disk_path' in build_options else default_settings['qemu_virtio_disk_path']
templeos_iso_file = build_options['templeos_iso_file'] if 'templeos_iso_file' in build_options else default_settings['templeos_iso_file']
qemu_args = build_options['qemu_args'] if 'qemu_args' in build_options else [
'-display sdl,grab-mod=rctrl',
'-enable-kvm',
'-smp cores=4',
'-m 8192',
'-netdev tap,id=mynet0,ifname=tap0,script=no,downscript=no',
'-device ac97',
'-device virtio-net,netdev=mynet0',
'-drive file=' + qemu_virtio_disk_path + ',format=qcow2,if=none,index=0,media=disk,id=virtio-disk',
'-device virtio-blk-pci,drive=virtio-disk',
'-device vmmouse,i8042=i8042',
'-device vmware-svga',
'-cdrom ' + qemu_slipstream_iso_file,
'-debugcon stdio',
'-boot d'
]
qemu_run_cmd = ' '.join([qemu_bin_path] + qemu_args)
def build_options_bool(key):
if key not in build_options:
return False
return build_options[key] == True
def clang_format_src_files():
print("build-all: clang-format-src-files")
exclude_paths = ["stb_", "openlibm", "tlse", ".iso.c"]
format_file_extensions = [".c", ".cpp", ".h", ".hc"]
for src_file in glob.glob(project_path + "**", recursive=True):
exclude_file = False
for exclude_path in exclude_paths:
if src_file.lower().find(exclude_path) > 0:
exclude_file = True
if exclude_file:
continue
for format_file_extension in format_file_extensions:
if src_file.lower().endswith(format_file_extension):
print(src_file)
res = os.system('clang-format -i --style=file:' + project_path + '.clang-format ' + src_file)
if res:
raise ValueError("build-all: step 'clang-format-src-files' failed, error code " + str(res))
def refresh_build_path():
print("build-all: refresh-build-path")
res = os.system('rm -rf ' + project_path + 'build && mkdir -p ' + project_path + 'build/bin && mkdir -p ' + project_path + 'build/isoc && mkdir -p ' + project_path + 'build/lib && mkdir -p ' + project_path + 'build/redsea')
if res:
raise ValueError("build-all: step 'refresh-build-path' failed, error code " + str(res))
def build_image():
print("build-all: build-image")
build_specific_options = '-Wl,--section-start=.text=0x1004000 -Wl,--section-start=.plt=0x1002020 -no-pie'
res = os.system('cd ' + project_path + '&& cd src/image && gcc -o ../../build/bin/image ' + build_specific_options + ' -O0 -mno-mmx -mno-red-zone image.c')
if res:
raise ValueError("build-all: step 'build-image' failed, error code " + str(res))
def build_truetype():
print("build-all: build-truetype")
build_specific_options = '-Wl,--section-start=.text=0x1104000 -Wl,--section-start=.plt=0x1102020 -no-pie'
res = os.system('cd ' + project_path + '&& cd src/truetype && gcc -o ../../build/bin/truetype ' + build_specific_options + ' -O0 -mno-mmx -mno-red-zone truetype.c ../../build/lib/libtemple.so ../openlibm/libopenlibm.a')
if res:
raise ValueError("build-all: step 'build-image' failed, error code " + str(res))
def build_libtemple():
print("build-all: build-libtemple")
res = os.system('cd ' + project_path + 'src/libtemple && g++ -c -o ../../build/libtemple.o libtemple.cpp && gcc -shared -o ../../build/lib/libtemple.so ../../build/libtemple.o && rm ' + project_path + 'build/libtemple.o')
if res:
raise ValueError("build-all: step 'build-libtemple' failed, error code " + str(res))
def build_openlibm():
print("build-all: build-openlibm")
res = os.system('cd ' + project_path + 'src/openlibm && make clean && make ARCH=amd64')
if res:
raise ValueError("build-all: step 'build-openlibm' failed, error code " + str(res))
def build_tlse():
print("build-all: build-tlse")
build_specific_options = '-Wl,--section-start=.text=0x1204000 -Wl,--section-start=.plt=0x1202020 -no-pie'
res = os.system('cd ' + project_path + '&& cd src/tlse && gcc -o ../../build/bin/tlse ' + build_specific_options + ' -O0 -mno-mmx -mno-red-zone -DTLS_AMALGAMATION tlse.c')
if res:
raise ValueError("build-all: step 'build-tlse' failed, error code " + str(res))
def transpile_net_to_sepples():
print("build-all: transpile-net-to-sepples")
res = os.system('cd ' + project_path + 'src/net && ' + jakt_compiler_path + ' -S -R ' + jakt_runtime_path + ' -B ' + project_path + 'build/net -O net.jakt')
if res:
raise ValueError("build-all: step 'transpile-net-to-sepples' failed, error code " + str(res))
def build_net():
print("build-all: build-net")
build_specific_options = '-Wno-invalid-offsetof -Wl,--section-start=.text=0x1404000 -Wl,--section-start=.plt=0x1402020 -no-pie'
res = os.system('cd ' + project_path + 'build/net && clang++-19 ' + build_specific_options + ' -O3 -I ' + jakt_runtime_path + ' -I ' + project_path + '/src/libtemple -fcolor-diagnostics -std=c++20 -fno-exceptions -Wno-user-defined-literals -Wno-deprecated-declarations -Wno-parentheses-equality -Wno-unqualified-std-cast-call -Wno-unknown-warning-option -Wno-int-to-pointer-cast -mno-red-zone -o ../bin/net *.cpp ../lib/libtemple.so ' + jakt_lib_path + 'libjakt_runtime_x86_64-unknown-linux-unknown.a ' + jakt_lib_path + 'libjakt_main_x86_64-unknown-linux-unknown.a && cd .. && rm -rf net')
if res:
raise ValueError("build-all: step 'build-net' failed, error code " + str(res))
def address_string_for_symbol(file, symbol):
p = subprocess.Popen('readelf -s --wide "' + file + '" | grep \'' + symbol + '$\' | awk \'{sub("000000000", "0x", $2); print $2}\'', shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
return str(p.communicate()[0][:-1].decode(encoding='utf-8'))
def image_hc_fixup(macro, symbol, image_bin_path, image_hc_path):
os.system('echo -e "#define ' + macro + ' ' + address_string_for_symbol(image_bin_path, symbol) + '\n" | cat - ' + image_hc_path + ' | sponge ' + image_hc_path)
return
def truetype_hc_fixup(macro, symbol, truetype_bin_path, truetype_hc_path):
os.system('echo -e "#define ' + macro + ' ' + address_string_for_symbol(truetype_bin_path, symbol) + '\n" | cat - ' + truetype_hc_path + ' | sponge ' + truetype_hc_path)
return
def tlse_hc_fixup(macro, symbol, tlse_bin_path, tlse_hc_path):
os.system('echo -e "#define ' + macro + ' ' + address_string_for_symbol(tlse_bin_path, symbol) + '\n" | cat - ' + tlse_hc_path + ' | sponge ' + tlse_hc_path)
return
def generate_iso_c_file():
print("build-all: generate-iso-c-file")
step_error_message = "build-all: step 'generate-iso-c-file' failed, error code "
try:
os.remove(isoc_file)
except:
pass
res = os.system('isoc-mount --rw ' + isoc_file + ' ' + redsea_path)
if res:
raise ValueError(step_error_message + str(res))
time.sleep(0.25)
copy_files_cmd_line = 'rsync -av --inplace --progress ' + project_path + ' ' + redsea_path
copy_files_cmd_line += ' --exclude .clang-format'
copy_files_cmd_line += ' --exclude .git'
copy_files_cmd_line += ' --exclude .gitignore'
copy_files_cmd_line += ' --exclude .vscode'
copy_files_cmd_line += ' --exclude build/isoc'
copy_files_cmd_line += ' --exclude build/lib'
copy_files_cmd_line += ' --exclude build/redsea'
copy_files_cmd_line += ' --exclude scripts'
copy_files_cmd_line += ' --exclude src'
res = os.system(copy_files_cmd_line)
if res:
raise ValueError(step_error_message + str(res))
if 'custom_files_path' in build_options:
copy_custom_files_cmd_line = 'rsync -av --inplace --progress ' + build_options['custom_files_path'] + ' ' + redsea_path
res = os.system(copy_custom_files_cmd_line)
if res:
raise ValueError(step_error_message + str(res))
# Fixup addresses for Image.HC
image_bin_path = redsea_path + '/build/bin/image'
image_hc_path = redsea_path + '/System/Utilities/Image.HC'
image_hc_fixup('IMAGE_LOAD_GIF_FROM_MEMORY', 'image_load_gif_from_memory', image_bin_path, image_hc_path)
image_hc_fixup('STBI_WRITE_PNG_TO_MEM', 'stbi_write_png_to_mem', image_bin_path, image_hc_path)
image_hc_fixup('STBI_LOAD_FROM_MEMORY', 'stbi_load_from_memory', image_bin_path, image_hc_path)
image_hc_fixup('STBI_INFO_FROM_MEMORY', 'stbi_info_from_memory', image_bin_path, image_hc_path)
image_hc_fixup('STBI_FAILURE_REASON', 'stbi_failure_reason', image_bin_path, image_hc_path)
image_hc_fixup('RENDER_4BIT_FLOYDSTEIN', 'render_4bit_floydstein', image_bin_path, image_hc_path)
# Fixup addresses for TrueType.HC
truetype_bin_path = redsea_path + '/build/bin/truetype'
truetype_hc_path = redsea_path + '/System/Utilities/TrueType.HC'
truetype_hc_fixup('STBTT_INITFONT', 'stbtt_InitFont', truetype_bin_path, truetype_hc_path)
truetype_hc_fixup('STBTT_RENDERTEXT', 'stbtt_RenderText', truetype_bin_path, truetype_hc_path)
truetype_hc_fixup('STBTT_GETTEXTWIDTH', 'stbtt_GetTextWidth', truetype_bin_path, truetype_hc_path)
truetype_hc_fixup('STBTT_GETFONTNAMEDEFAULT', 'stbtt_GetFontNameDefault', truetype_bin_path, truetype_hc_path)
# Fixup addresses for Tlse.HC
rsa_hc_path = redsea_path + '/System/Libraries/Rsa.HC'
tlse_bin_path = redsea_path + '/build/bin/tlse'
tlse_hc_path = redsea_path + '/System/Libraries/Tlse.HC'
tlse_hc_fixup('RSA_IMPORT', 'rsa_import', tlse_bin_path, rsa_hc_path)
tlse_hc_fixup('RSA_CREATE_SIGNATURE', 'rsa_create_signature', tlse_bin_path, rsa_hc_path)
tlse_hc_fixup('RSA_VERIFY_SIGNATURE', 'rsa_verify_signature', tlse_bin_path, rsa_hc_path)
tlse_hc_fixup('TLS_CREATE_CONTEXT', 'tls_create_context', tlse_bin_path, tlse_hc_path)
tlse_hc_fixup('TLS_SNI_SET', 'tls_sni_set', tlse_bin_path, tlse_hc_path)
tlse_hc_fixup('TLS_CLIENT_CONNECT', 'tls_client_connect', tlse_bin_path, tlse_hc_path)
tlse_hc_fixup('TLS_CONNECTION_STATUS', 'tls_connection_status', tlse_bin_path, tlse_hc_path)
tlse_hc_fixup('TLS_GET_WRITE_BUFFER', 'tls_get_write_buffer', tlse_bin_path, tlse_hc_path)
tlse_hc_fixup('TLS_BUFFER_CLEAR', 'tls_buffer_clear', tlse_bin_path, tlse_hc_path)
tlse_hc_fixup('TLS_CONSUME_STREAM', 'tls_consume_stream', tlse_bin_path, tlse_hc_path)
tlse_hc_fixup('TLS_READ', 'tls_read', tlse_bin_path, tlse_hc_path)
tlse_hc_fixup('TLS_WRITE', 'tls_write', tlse_bin_path, tlse_hc_path)
tlse_hc_fixup('TLS_ESTABLISHED', 'tls_established', tlse_bin_path, tlse_hc_path)
time.sleep(0.25)
res = os.system('sync && fusermount -u ' + redsea_path)
if res:
raise ValueError(step_error_message + str(res))
time.sleep(0.25)
def generate_slipstream_iso_file():
print("build-all: generate-slipstream-iso-file")
res = os.system('templeos-slipstream ' + templeos_iso_file + ' ' + isoc_file + ' ' + qemu_slipstream_iso_file)
if res:
raise ValueError("build-all: step 'generate-slipstream-iso-file' failed, error code " + str(res))
def run():
print("build-all: run")
res = os.system(qemu_run_cmd)
if res:
raise ValueError("build-all: step 'run' failed, error code " + str(res))
def build_all():
if not build_options_bool('skip_clang_format'):
clang_format_src_files()
if not build_options_bool('skip_rebuild'):
refresh_build_path()
build_image()
build_openlibm()
build_libtemple()
build_truetype()
build_tlse()
transpile_net_to_sepples()
build_net()
generate_iso_c_file()
generate_slipstream_iso_file()
run()
build_all()