Add commands to deal with Orca source code:

- Add a vendor commands
- Add a command that helps you set up a C compiler
- Move ext into the src folder
- Update Mac build scripts for consistency
- Update Windows batch scripts
This commit is contained in:
Ben Visness 2023-08-28 22:15:16 -05:00 committed by Martin Fouilleul
parent 731b1c7334
commit 29cb9f50e4
326 changed files with 487 additions and 215 deletions

4
.gitignore vendored
View File

@ -35,6 +35,8 @@ src/graphics/orca_gl31.h
__pycache__
scripts/files
ext/angle
# explicitly abandon old ext dir
/ext
src/ext/angle
sketches/*/bin

View File

@ -1,4 +0,0 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

View File

@ -1,15 +0,0 @@
M3_SRC_DIR := ../../../source
SOURCES := ../../app/main.c \
$(shell find $(M3_SRC_DIR) -type f -name '*.c')
override CFLAGS += -std=c99 -O3 -flto -Dd_m3HasWASI -Wno-error=format-security -Wfatal-errors -I$(M3_SRC_DIR)
all: wasm3
wasm3: $(SOURCES)
$(CC) $(CFLAGS) $(SOURCES) -o wasm3 -lm
clean:
$(RM) wasm3

6
orca
View File

@ -41,9 +41,9 @@ if use_source:
# Use the source checkout's scripts instead of the system-installed scripts.
if not is_source:
print("The Orca tool is running from a local source checkout and will")
print("use that instead of the system Orca installation.")
print()
print("The Orca tool is running from a local source checkout and will", file=sys.stderr)
print("use that instead of the system Orca installation.", file=sys.stderr)
print(file=sys.stderr)
sys.path.append(source_dir)
import scripts.orca

View File

@ -1,19 +1,21 @@
@echo off
set ORCA_DIR=..\..
set STDLIB_DIR=%ORCA_DIR%\src\libc-shim
:: compile wasm module
set wasmFlags=--target=wasm32^
--no-standard-libraries ^
-fno-builtin ^
-mbulk-memory ^
-g -O2 ^
-D__ORCA__ ^
-Wl,--no-entry ^
-Wl,--export-dynamic ^
-g ^
-O2 ^
-mbulk-memory ^
-D__ORCA__ ^
-isystem ..\..\src\libc-shim\include ^
-I..\..\ext -I ..\..\src
-isystem %STDLIB_DIR%\include ^
-I%ORCA_DIR%\src ^
-I%ORCA_DIR%\src\ext
clang %wasmFlags% -o .\module.wasm ..\..\src\orca.c ..\..\src\libc-shim\src\*.c src\main.c
clang %wasmFlags% -o .\module.wasm %ORCA_DIR%\src\orca.c %STDLIB_DIR%\src\*.c src\main.c
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
orca bundle --orca-dir ..\.. --name Breakout --icon icon.png --resource-dir data module.wasm
orca bundle --orca-dir %ORCA_DIR% --name Breakout --icon icon.png --resource-dir data module.wasm

View File

@ -12,21 +12,19 @@ else
fi
ORCA_DIR=../..
STDLIB_DIR=../../src/libc-shim
STDLIB_DIR=$ORCA_DIR/src/libc-shim
wasmFlags="--target=wasm32 \
--no-standard-libraries \
-fno-builtin \
-mbulk-memory \
-g -O2 \
-D__ORCA__ \
-Wl,--no-entry \
-Wl,--export-dynamic \
-g \
-O2 \
-mbulk-memory \
-D__ORCA__ \
-I $STDLIB_DIR/include \
-I $ORCA_DIR/ext \
-I $ORCA_DIR/src"
-isystem $STDLIB_DIR/include \
-I $ORCA_DIR/src \
-I $ORCA_DIR/src/ext"
$CLANG $wasmFlags -o ./module.wasm ../../src/orca.c $STDLIB_DIR/src/*.c src/main.c
$CLANG $wasmFlags -o ./module.wasm $ORCA_DIR/src/orca.c $STDLIB_DIR/src/*.c src/main.c
orca bundle --orca-dir ../.. --name Breakout --icon icon.png --resource-dir data module.wasm
orca bundle --orca-dir $ORCA_DIR --name Breakout --icon icon.png --resource-dir data module.wasm

View File

@ -1,19 +1,21 @@
@echo off
set ORCA_DIR=..\..
set STDLIB_DIR=%ORCA_DIR%\src\libc-shim
:: compile wasm module
set wasmFlags=--target=wasm32^
--no-standard-libraries ^
-fno-builtin ^
-mbulk-memory ^
-g -O2 ^
-D__ORCA__ ^
-Wl,--no-entry ^
-Wl,--export-dynamic ^
-g ^
-O2 ^
-mbulk-memory ^
-D__ORCA__ ^
-isystem ..\..\src\libc-shim\include ^
-I..\..\ext -I ..\..\src
-isystem %STDLIB_DIR%\include ^
-I%ORCA_DIR%\src ^
-I%ORCA_DIR%\src\ext
clang %wasmFlags% -o .\module.wasm ..\..\src\orca.c ..\..\src\libc-shim\src\*.c src\main.c
clang %wasmFlags% -o .\module.wasm %ORCA_DIR%\src\orca.c %STDLIB_DIR%\src\*.c src\main.c
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
orca bundle --orca-dir ..\.. --name Clock --icon icon.png --resource-dir data module.wasm
orca bundle --orca-dir %ORCA_DIR% --name Clock --icon icon.png --resource-dir data module.wasm

View File

@ -12,21 +12,19 @@ else
fi
ORCA_DIR=../..
STDLIB_DIR=../../src/libc-shim
STDLIB_DIR=$ORCA_DIR/src/libc-shim
wasmFlags="--target=wasm32 \
--no-standard-libraries \
-fno-builtin \
-mbulk-memory \
-g -O2 \
-D__ORCA__ \
-Wl,--no-entry \
-Wl,--export-dynamic \
-g \
-O2 \
-mbulk-memory \
-D__ORCA__ \
-I $STDLIB_DIR/include \
-I $ORCA_DIR/ext \
-I $ORCA_DIR/src"
-isystem $STDLIB_DIR/include \
-I $ORCA_DIR/src \
-I $ORCA_DIR/src/ext"
$CLANG $wasmFlags -o ./module.wasm ../../src/orca.c $STDLIB_DIR/src/*.c src/main.c
$CLANG $wasmFlags -o ./module.wasm $ORCA_DIR/src/orca.c $STDLIB_DIR/src/*.c src/main.c
orca bundle --orca-dir ../.. --name Clock --icon icon.png --resource-dir data module.wasm
orca bundle --orca-dir $ORCA_DIR --name Clock --icon icon.png --resource-dir data module.wasm

View File

@ -1,17 +1,19 @@
@echo off
set ORCA_DIR=..\..
set STDLIB_DIR=%ORCA_DIR%\src\libc-shim
:: compile wasm module
set wasmFlags=--target=wasm32^
--no-standard-libraries ^
-fno-builtin ^
-mbulk-memory ^
-g -O2 ^
-D__ORCA__ ^
-Wl,--no-entry ^
-Wl,--export-dynamic ^
-g ^
-O2 ^
-mbulk-memory ^
-D__ORCA__ ^
-isystem ..\..\src\libc-shim\include ^
-I..\..\ext -I ..\..\src
-isystem %STDLIB_DIR%\include ^
-I%ORCA_DIR%\src ^
-I%ORCA_DIR%\src\ext
set shaders=src/shaders/advect.glsl^
src/shaders/blit_div_fragment.glsl^
@ -31,7 +33,7 @@ set shaders=src/shaders/advect.glsl^
call python3 ../../scripts/embed_text_files.py --prefix=glsl_ --output src/glsl_shaders.h %shaders%
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
clang %wasmFlags% -o .\module.wasm ..\..\src\orca.c ..\..\src\libc-shim\src\*.c src\main.c
clang %wasmFlags% -o .\module.wasm %ORCA_DIR%\src\orca.c %STDLIB_DIR%\src\*.c src\main.c
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
orca bundle --orca-dir ..\.. --icon icon.png --name Fluid module.wasm
orca bundle --orca-dir %ORCA_DIR% --name Fluid --icon icon.png module.wasm

View File

@ -12,23 +12,21 @@ else
fi
ORCA_DIR=../..
STDLIB_DIR=../../src/libc-shim
STDLIB_DIR=$ORCA_DIR/src/libc-shim
python3 ../../scripts/embed_text_files.py --prefix=glsl_ --output src/glsl_shaders.h src/shaders/*.glsl
wasmFlags="--target=wasm32 \
--no-standard-libraries \
-fno-builtin \
-mbulk-memory \
-g -O2 \
-D__ORCA__ \
-Wl,--no-entry \
-Wl,--export-dynamic \
-g \
-O2 \
-mbulk-memory \
-D__ORCA__ \
-I $STDLIB_DIR/include \
-I $ORCA_DIR/ext \
-I $ORCA_DIR/src"
-isystem $STDLIB_DIR/include \
-I $ORCA_DIR/src \
-I $ORCA_DIR/src/ext"
$CLANG $wasmFlags -o ./module.wasm ../../src/orca.c $STDLIB_DIR/src/*.c src/main.c
$CLANG $wasmFlags -o ./module.wasm $ORCA_DIR/src/orca.c $STDLIB_DIR/src/*.c src/main.c
orca bundle --orca-dir ../.. --icon icon.png --name Fluid module.wasm
orca bundle --orca-dir $ORCA_DIR --name Fluid --icon icon.png module.wasm

View File

@ -1,19 +1,21 @@
@echo off
set ORCA_DIR=..\..
set STDLIB_DIR=%ORCA_DIR%\src\libc-shim
:: compile wasm module
set wasmFlags=--target=wasm32^
--no-standard-libraries ^
-fno-builtin ^
-mbulk-memory ^
-g -O2 ^
-D__ORCA__ ^
-Wl,--no-entry ^
-Wl,--export-dynamic ^
-g ^
-O2 ^
-mbulk-memory ^
-D__ORCA__ ^
-isystem ..\..\src\libc-shim\include ^
-I..\..\ext -I ..\..\src
-isystem %STDLIB_DIR%\include ^
-I%ORCA_DIR%\src ^
-I%ORCA_DIR%\src\ext
clang %wasmFlags% -o .\module.wasm ..\..\src\orca.c ..\..\src\libc-shim\src\*.c src\main.c
clang %wasmFlags% -o .\module.wasm %ORCA_DIR%\src\orca.c %STDLIB_DIR%\src\*.c src\main.c
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
orca bundle --orca-dir ..\.. --name Triangle module.wasm
orca bundle --orca-dir %ORCA_DIR% --name Triangle module.wasm

View File

@ -12,21 +12,19 @@ else
fi
ORCA_DIR=../..
STDLIB_DIR=../../src/libc-shim
STDLIB_DIR=$ORCA_DIR/src/libc-shim
wasmFlags="--target=wasm32 \
--no-standard-libraries \
-fno-builtin \
-mbulk-memory \
-g -O2 \
-D__ORCA__ \
-Wl,--no-entry \
-Wl,--export-dynamic \
-g \
-O2 \
-mbulk-memory \
-D__ORCA__ \
-I $STDLIB_DIR/include \
-I $ORCA_DIR/ext \
-I $ORCA_DIR/src"
-isystem $STDLIB_DIR/include \
-I $ORCA_DIR/src \
-I $ORCA_DIR/src/ext"
$CLANG $wasmFlags -o ./module.wasm ../../src/orca.c ../../src/libc-shim/src/*.c src/main.c
$CLANG $wasmFlags -o ./module.wasm $ORCA_DIR/src/orca.c $STDLIB_DIR/src/*.c src/main.c
orca bundle --orca-dir ../.. --name Triangle module.wasm
orca bundle --orca-dir $ORCA_DIR --name Triangle module.wasm

View File

@ -1,19 +1,21 @@
@echo off
set ORCA_DIR=..\..
set STDLIB_DIR=%ORCA_DIR%\src\libc-shim
:: compile wasm module
set wasmFlags=--target=wasm32^
--no-standard-libraries ^
-fno-builtin ^
-mbulk-memory ^
-g -O2 ^
-D__ORCA__ ^
-Wl,--no-entry ^
-Wl,--export-dynamic ^
-g ^
-O2 ^
-mbulk-memory ^
-D__ORCA__ ^
-isystem ..\..\src\libc-shim\include ^
-I..\..\ext -I ..\..\src
-isystem %STDLIB_DIR%\include ^
-I%ORCA_DIR%\src ^
-I%ORCA_DIR%\src\ext
clang %wasmFlags% -o .\module.wasm ..\..\src\orca.c ..\..\src\libc-shim\src\*.c src\main.c
clang %wasmFlags% -o .\module.wasm %ORCA_DIR%\src\orca.c %STDLIB_DIR%\src\*.c src\main.c
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
orca bundle --orca-dir ..\.. --name UI --resource-dir data module.wasm
orca bundle --orca-dir %ORCA_DIR% --name UI --resource-dir data module.wasm

View File

@ -12,21 +12,19 @@ else
fi
ORCA_DIR=../..
STDLIB_DIR=../../src/libc-shim
STDLIB_DIR=$ORCA_DIR/src/libc-shim
wasmFlags="--target=wasm32 \
--no-standard-libraries \
-mbulk-memory \
-g -O2 \
-D__ORCA__ \
-Wl,--no-entry \
-Wl,--export-dynamic \
-g \
-O2 \
-mbulk-memory \
-D__ORCA__ \
-I $ORCA_DIR/ext \
-I $STDLIB_DIR/include \
-I $ORCA_DIR/ext \
-I $ORCA_DIR/src"
-isystem $STDLIB_DIR/include \
-I $ORCA_DIR/src \
-I $ORCA_DIR/src/ext"
$CLANG $wasmFlags -o ./module.wasm ../../src/orca.c $STDLIB_DIR/src/*.c src/main.c
$CLANG $wasmFlags -o ./module.wasm $ORCA_DIR/src/orca.c $STDLIB_DIR/src/*.c src/main.c
orca bundle --orca-dir ../.. --name UI --resource-dir data module.wasm
orca bundle --orca-dir $ORCA_DIR --name UI --resource-dir data module.wasm

View File

@ -70,8 +70,8 @@ def macos_make_app(args):
#-----------------------------------------------------------
orca_exe = os.path.join(args.orca_dir, 'build/bin/orca_runtime')
orca_lib = os.path.join(args.orca_dir, 'build/bin/liborca.dylib')
gles_lib = os.path.join(args.orca_dir, 'ext/angle/bin/libGLESv2.dylib')
egl_lib = os.path.join(args.orca_dir, 'ext/angle/bin/libEGL.dylib')
gles_lib = os.path.join(args.orca_dir, 'src/ext/angle/bin/libGLESv2.dylib')
egl_lib = os.path.join(args.orca_dir, 'src/ext/angle/bin/libEGL.dylib')
renderer_lib = os.path.join(args.orca_dir, 'build/bin/mtl_renderer.metallib')
shutil.copy(orca_exe, exe_dir)

View File

@ -1,10 +1,10 @@
{
"scripts/files/angle-windows-2019-2023-07-05.zip": "a333b5ccc8462151ee8df65c43cfacd70d9db2413f2e495da65670737b5b2d96",
"scripts/files/angle-macos-jank-2023-07-05.zip": "c234b8db179a24757ab9f46610a032123718dd9bed967d2bf8e27d0d17eb0aff",
"ext/angle/bin/libEGL.dll": "b7bf51f83e88129ddc20c0c2cb904ec04c89059a30a2cd29b9b1ea11c80388fb",
"ext/angle/lib/libEGL.dll.lib": "4cec54c534136da413dea86bd271ccb9c5ae88e40aa91d1de7a01e701be8e1d7",
"ext/angle/bin/libGLESv2.dll": "193b53b0a16b702eaa28a73e84527acf7aecfd665e3e3f54a8d9db9ae73111e1",
"ext/angle/lib/libGLESv2.dll.lib": "ee87aac129efe8fe871825d181b85da1b1ea6626cb48be52c2e689f2804b953f",
"ext/angle/bin/libEGL.dylib": "96baea4b1c8578d30738764784d07b509d1153df694c094faba2ee8ccbfde2a9",
"ext/angle/bin/libGLESv2.dylib": "98ce9f6248a6447ba9199e96b8f6d87df9548d43ce583a2615717aab168ecb71"
}
"src/ext/angle/bin/libEGL.dll": "b7bf51f83e88129ddc20c0c2cb904ec04c89059a30a2cd29b9b1ea11c80388fb",
"src/ext/angle/lib/libEGL.dll.lib": "4cec54c534136da413dea86bd271ccb9c5ae88e40aa91d1de7a01e701be8e1d7",
"src/ext/angle/bin/libGLESv2.dll": "193b53b0a16b702eaa28a73e84527acf7aecfd665e3e3f54a8d9db9ae73111e1",
"src/ext/angle/lib/libGLESv2.dll.lib": "ee87aac129efe8fe871825d181b85da1b1ea6626cb48be52c2e689f2804b953f",
"src/ext/angle/bin/libEGL.dylib": "96baea4b1c8578d30738764784d07b509d1153df694c094faba2ee8ccbfde2a9",
"src/ext/angle/bin/libGLESv2.dylib": "98ce9f6248a6447ba9199e96b8f6d87df9548d43ce583a2615717aab168ecb71"
}

View File

@ -1,4 +1,3 @@
from datetime import datetime
import glob
import os
import platform
@ -11,14 +10,15 @@ from . import checksum
from .bindgen import bindgen
from .gles_gen import gles_gen
from .log import *
from .utils import pushd, removeall
from .utils import pushd, removeall, yeetdir, yeetfile
from .embed_text_files import *
from .version import check_if_source, is_orca_source, orca_version
ANGLE_VERSION = "2023-07-05"
def attach_dev_commands(subparsers):
dev_cmd = subparsers.add_parser("dev", help="Commands for building Orca itself. Must be run from the root of an Orca source checkout.")
dev_cmd = subparsers.add_parser("dev", help="Commands for building Orca itself. Must be run from within an Orca source checkout.")
dev_cmd.set_defaults(func=orca_source_only)
dev_sub = dev_cmd.add_subparsers(required=is_orca_source(), title='commands')
@ -38,38 +38,6 @@ def attach_dev_commands(subparsers):
uninstall_cmd.set_defaults(func=dev_shellish(uninstall))
# Checks if the Orca tool should use a source checkout of Orca instead of a system install.
# This is copy-pasted to the command-line tool so it can work before loading anything.
#
# Returns: (use source, source directory, is actually the source's tool)
def check_if_source():
def path_is_in_orca_source(path):
dir = path
while True:
try:
os.stat(os.path.join(dir, ".orcaroot"))
return (True, dir)
except FileNotFoundError:
pass
newdir = os.path.dirname(dir)
if newdir == dir: # TODO: Verify on Windows (it will probably not work)
return (False, None)
dir = newdir
in_source, current_source_dir = path_is_in_orca_source(os.getcwd())
script_is_source, script_source_dir = path_is_in_orca_source(os.path.dirname(os.path.abspath(__file__)))
use_source = in_source or script_is_source
source_dir = current_source_dir or script_source_dir
return (use_source, source_dir, script_is_source)
def is_orca_source():
use_source, _, _ = check_if_source()
return use_source
def orca_source_only(args):
print("The Orca dev commands can only be run from an Orca source checkout.")
print()
@ -99,10 +67,10 @@ def build_runtime(args):
def clean(args):
yeet("build")
yeet("ext/angle")
yeet("scripts/files")
yeet("scripts/__pycache__")
yeetdir("build")
yeetdir("src/ext/angle")
yeetdir("scripts/files")
yeetdir("scripts/__pycache__")
def build_platform_layer(target, release):
@ -145,8 +113,8 @@ def build_platform_layer_lib_win(release):
includes = [
"/I", "src",
"/I", "ext",
"/I", "ext/angle/include",
"/I", "src/ext",
"/I", "src/ext/angle/include",
]
libs = [
"user32.lib",
@ -161,7 +129,7 @@ def build_platform_layer_lib_win(release):
"shlwapi.lib",
"dxgi.lib",
"dxguid.lib",
"/LIBPATH:ext/angle/lib",
"/LIBPATH:src/ext/angle/lib",
"libEGL.dll.lib",
"libGLESv2.dll.lib",
"/DELAYLOAD:libEGL.dll",
@ -189,7 +157,7 @@ def build_platform_layer_lib_mac(release):
cflags = ["-std=c11"]
debug_flags = ["-O3"] if release else ["-g", "-DOC_DEBUG", "-DOC_LOG_COMPILE_DEBUG"]
ldflags = [f"-L{sdk_dir}/usr/lib", f"-F{sdk_dir}/System/Library/Frameworks/"]
includes = ["-Isrc", "-Isrc/util", "-Isrc/platform", "-Iext", "-Iext/angle/include"]
includes = ["-Isrc", "-Isrc/util", "-Isrc/platform", "-Isrc/ext", "-Isrc/ext/angle/include"]
# compile metal shader
subprocess.run([
@ -228,7 +196,7 @@ def build_platform_layer_lib_mac(release):
*ldflags, "-dylib",
"-o", "build/bin/liborca.dylib",
"build/orca_c.o", "build/orca_objc.o",
"-Lext/angle/bin", "-lc",
"-Lsrc/ext/angle/bin", "-lc",
"-framework", "Carbon", "-framework", "Cocoa", "-framework", "Metal", "-framework", "QuartzCore",
"-weak-lEGL", "-weak-lGLESv2",
], check=True)
@ -271,14 +239,14 @@ def build_wasm3(release):
def build_wasm3_lib_win(release):
for f in glob.iglob("./ext/wasm3/source/*.c"):
for f in glob.iglob("./src/ext/wasm3/source/*.c"):
name = os.path.splitext(os.path.basename(f))[0]
subprocess.run([
"cl", "/nologo",
"/Zi", "/Zc:preprocessor", "/c",
"/O2",
f"/Fo:build/obj/{name}.obj",
"/I", "./ext/wasm3/source",
"/I", "./src/ext/wasm3/source",
f,
], check=True)
subprocess.run([
@ -288,7 +256,7 @@ def build_wasm3_lib_win(release):
def build_wasm3_lib_mac(release):
includes = ["-Iext/wasm3/source"]
includes = ["-Isrc/ext/wasm3/source"]
debug_flags = ["-g", "-O2"]
flags = [
*debug_flags,
@ -297,7 +265,7 @@ def build_wasm3_lib_mac(release):
"-Dd_m3VerboseErrorMessages",
]
for f in glob.iglob("ext/wasm3/source/*.c"):
for f in glob.iglob("src/ext/wasm3/source/*.c"):
name = os.path.splitext(os.path.basename(f))[0] + ".o"
subprocess.run([
"clang", "-c", *flags, *includes,
@ -330,9 +298,9 @@ def build_orca_win(release):
# compile orca
includes = [
"/I", "src",
"/I", "ext",
"/I", "ext/angle/include",
"/I", "ext/wasm3/source",
"/I", "src/ext",
"/I", "src/ext/angle/include",
"/I", "src/ext/wasm3/source",
]
libs = [
"/LIBPATH:build/bin",
@ -355,9 +323,9 @@ def build_orca_mac(release):
includes = [
"-Isrc",
"-Iext",
"-Iext/angle/include",
"-Iext/wasm3/source"
"-Isrc/ext",
"-Isrc/ext/angle/include",
"-Isrc/ext/wasm3/source"
]
libs = ["-Lbuild/bin", "-Lbuild/lib", "-lorca", "-lwasm3"]
debug_flags = ["-O2"] if release else ["-g", "-DOC_DEBUG -DOC_LOG_COMPILE_DEBUG"]
@ -390,7 +358,7 @@ def build_orca_mac(release):
def gen_all_bindings():
gles_gen("ext/gl.xml",
gles_gen("src/ext/gl.xml",
"src/wasmbind/gles_api.json",
"src/graphics/orca_gl31.h"
)
@ -459,15 +427,15 @@ def verify_angle():
checkfiles = None
if platform.system() == "Windows":
checkfiles = [
"ext/angle/bin/libEGL.dll",
"ext/angle/lib/libEGL.dll.lib",
"ext/angle/bin/libGLESv2.dll",
"ext/angle/lib/libGLESv2.dll.lib",
"src/ext/angle/bin/libEGL.dll",
"src/ext/angle/lib/libEGL.dll.lib",
"src/ext/angle/bin/libGLESv2.dll",
"src/ext/angle/lib/libGLESv2.dll.lib",
]
elif platform.system() == "Darwin":
checkfiles = [
"ext/angle/bin/libEGL.dylib",
"ext/angle/bin/libGLESv2.dylib",
"src/ext/angle/bin/libEGL.dylib",
"src/ext/angle/bin/libGLESv2.dylib",
]
if checkfiles is None:
@ -512,11 +480,7 @@ def download_angle():
with ZipFile(filepath, "r") as anglezip:
anglezip.extractall(path="scripts/files")
shutil.copytree(f"scripts/files/angle/", "ext/angle", dirs_exist_ok=True)
def yeet(path):
os.makedirs(path, exist_ok=True)
shutil.rmtree(path)
shutil.copytree(f"scripts/files/angle/", "src/ext/angle", dirs_exist_ok=True)
def prompt(msg):
@ -529,29 +493,40 @@ def prompt(msg):
else:
print("Please enter \"yes\" or \"no\" and press return.")
def install_path():
def install_dir():
if platform.system() == "Windows":
orca_dir = os.path.join(os.getenv("LOCALAPPDATA"), "orca")
return os.path.join(os.getenv("LOCALAPPDATA"), "orca")
else:
orca_dir = os.path.expanduser(os.path.join("~", ".orca"))
bin_dir = os.path.join(orca_dir, "bin")
return (orca_dir, bin_dir)
return os.path.expanduser(os.path.join("~", ".orca"))
def install(args):
dest, bin_dir = install_path()
dest = install_dir()
bin_dir = os.path.join(dest, "bin")
src_dir = os.path.join(dest, "src")
version_file = os.path.join(dest, ".orcaversion")
version = orca_version()
existing_version = None
try:
with open(version_file, "r") as f:
existing_version = f.read().strip()
except FileNotFoundError:
pass
if not args.no_confirm:
print("The Orca command-line tools will be installed to:")
print(f"The Orca command-line tools (version {version}) will be installed to:")
print(dest)
print()
if existing_version is not None:
print(f"This will overwrite version {existing_version}.")
print()
if not prompt("Proceed with the installation?"):
return
yeet(bin_dir)
yeetdir(bin_dir)
yeetdir(src_dir)
yeetfile(version_file)
# The MS Store version of Python does some really stupid stuff with AppData:
# https://git.handmade.network/hmn/orca/issues/32
@ -562,14 +537,19 @@ def install(args):
# paths we need, the following scripts work regardless of Python install.
#
# Also apparently you can't just do mkdir in a subprocess call here, hence the
# trivial batch script.
# trivial batch scripts.
if platform.system() == "Windows":
subprocess.run(["scripts\\mkdir.bat", bin_dir], check=True)
subprocess.run(["scripts\\mkdir.bat", src_dir], check=True)
subprocess.run(["scripts\\touch.bat", version_file], check=True)
shutil.copytree("scripts", os.path.join(bin_dir, "sys_scripts"))
shutil.copy("orca", bin_dir)
shutil.copytree("src", src_dir, dirs_exist_ok=True)
if platform.system() == "Windows":
shutil.copy("orca.bat", bin_dir)
with open(version_file, "w") as f:
f.write(version)
print()
if platform.system() == "Windows":
@ -582,7 +562,7 @@ def install(args):
print("Orca has been added to your PATH. Restart any open terminals to use it.")
else:
print("No worries. You can manually add Orca to your PATH in the Windows settings")
print("this in the Windows settings by searching for \"environment variables\".")
print("by searching for \"environment variables\".")
else:
print("The Orca tools have been installed. Make sure the Orca tools are on your PATH by")
print("adding the following to your shell config:")

View File

@ -1,15 +1,28 @@
#!/usr/bin/env python3
import argparse
import sys
from .bundle import attach_bundle_commands
from .source import attach_source_commands
from .dev import attach_dev_commands
from .version import attach_version_command
parser = argparse.ArgumentParser()
parser.add_argument("-?", action="help", help=argparse.SUPPRESS)
subparsers = parser.add_subparsers(required=True, title='commands')
subparsers = parser.add_subparsers(required=True, title="commands")
attach_bundle_commands(subparsers)
attach_source_commands(subparsers)
attach_dev_commands(subparsers)
attach_version_command(subparsers)
args = parser.parse_args()
# Hack to run the actual version command if we pass -v or --version.
# Using argparse action="version" requires us to pass a single string
# and doesn't allow us to run our own custom version-printing function.
argv = sys.argv[1:]
if argv[0] in ["-v", "--version"]:
argv = ["version"]
args = parser.parse_args(argv)
args.func(args)

189
scripts/source.py Normal file
View File

@ -0,0 +1,189 @@
import hashlib
import json
import os
import re
import shutil
from .log import *
from .utils import yeetdir
from .version import src_dir, orca_version
def attach_source_commands(subparsers):
source_cmd = subparsers.add_parser("source", help="Commands for helping compile the Orca source code into your project.")
source_sub = source_cmd.add_subparsers(title="commands")
cflags_cmd = source_sub.add_parser("cflags", help="Get help setting up a C or C++ compiler to compile the Orca source.")
cflags_cmd.add_argument("srcdir", nargs="?", default=src_dir(), help="the directory containing the Orca source code (defaults to system installation)")
cflags_cmd.set_defaults(func=shellish(cflags))
vendor_cmd = source_sub.add_parser("vendor", help="Copy the Orca source code into your project.")
vendor_cmd.add_argument("dir", type=str, help="the directory into which the Orca source code will be copied")
vendor_cmd.set_defaults(func=shellish(vendor))
def vendor(args):
# Verify that we are ok to vendor into the requested dir.
if os.path.exists(args.dir):
try:
with open(vendor_file_path(args.dir), "r") as f:
vendor_info = json.load(f)
version = vendor_info["version"]
print(f"Orca version {version} is currently installed in that directory.")
if vendor_checksum(args.dir) != vendor_info["checksum"]:
log_error(f"The contents of your vendor directory have been modified. This command will exit to avoid overwriting any local changes. To proceed, manually delete {args.dir} and try again.")
exit(1)
except FileNotFoundError:
if len(os.listdir(args.dir)) > 0:
log_error(f"The requested directory already exists and does not appear to contain Orca source code. To avoid deleting anything important, please either provide the correct path or manually empty {args.dir} first.")
exit(1)
yeetdir(args.dir)
shutil.copytree(src_dir(), args.dir)
with open(vendor_file_path(args.dir), "w") as f:
json.dump({
"version": orca_version(),
"checksum": vendor_checksum(args.dir),
}, f, indent=2)
print(f"Version {orca_version()} of the Orca source code has been copied to {args.dir}.")
def vendor_file_path(vendor_dir):
return os.path.join(vendor_dir, ".orcavendor")
def vendor_checksum(dir):
return dirhash(dir, excluded_extensions=["orcavendor"])
def cflags(args):
if not os.path.exists(os.path.join(args.srcdir, "orca.h")):
log_error(f"The provided path does not seem to contain the Orca source code: {args.srcdir}")
exit(1)
def path_contains(a, b):
a_abs = os.path.abspath(a)
b_abs = os.path.abspath(b)
return os.path.commonpath([a_abs, b_abs]) == a_abs
def nicepath(path):
path_abs = os.path.abspath(path)
if path_contains(os.getcwd(), path_abs):
return os.path.relpath(path_abs)
else:
return path_abs
include = nicepath(args.srcdir)
orcac = nicepath(os.path.join(args.srcdir, "orca.c"))
extinclude = nicepath(os.path.join(args.srcdir, "ext"))
sysinclude = nicepath(os.path.join(args.srcdir, "libc-shim/include"))
libcsource = nicepath(os.path.join(args.srcdir, "libc-shim/src/*.c"))
print("To compile Orca as part of your C or C++ project, you must:")
print(f"> Put the following directory on your SYSTEM include search path:")
print(f" {sysinclude}")
print(f"> Put the following directories on your include search path:")
print(f" {include}")
print(f" {extinclude}")
print(f"> Compile the following file as a single translation unit:")
print(f" {orcac}")
print(f"> Compile the following files as separate translation units:")
print(f" {libcsource}")
print()
print("The following clang flags are also required:")
print("> --target=wasm32 (to compile to wasm)")
print("> --no-standard-libraries (to use only our libc shim)")
print("> -mbulk-memory (to enable memset/memcpy intrinsics, which are required)")
print("> -D__ORCA__ (to signal that the Orca source code is being compiled to run on Orca itself)")
print("> -Wl,--no-entry (to prevent wasm-ld from looking for a _start symbol)")
print("> -Wl,--export-dynamic (to expose your module's functions to Orca)")
print()
print("And the following clang flags are recommended:")
print("> -g -O2 (to compile with optimizations and debug info)")
print()
print("Complete clang example:")
print()
print(f"clang --target=wasm32 --no-standard-libraries -mbulk-memory -g -O2 -D__ORCA__ -Wl,--no-entry -Wl,--export-dynamic -isystem {sysinclude} -I {include} -I {extinclude} {orcac} {libcsource} your-main.c")
print()
if not path_contains(os.getcwd(), args.srcdir):
print("If these paths look crazy to you, consider vendoring the source code into your")
print("project using `orca source vendor`.")
print()
# -----------------------------------------------------------------------------
# Directory-hashing implementation pulled from the checksumdir package on pypi.
# Licensed under the MIT license.
# -----------------------------------------------------------------------------
def dirhash(
dirname,
hash_func=hashlib.sha1,
excluded_files=None,
ignore_hidden=False,
followlinks=False,
excluded_extensions=None,
include_paths=False
):
if not excluded_files:
excluded_files = []
if not excluded_extensions:
excluded_extensions = []
if not os.path.isdir(dirname):
raise TypeError("{} is not a directory.".format(dirname))
hashvalues = []
for root, dirs, files in os.walk(dirname, topdown=True, followlinks=followlinks):
if ignore_hidden and re.search(r"/\.", root):
continue
dirs.sort()
files.sort()
for fname in files:
if ignore_hidden and fname.startswith("."):
continue
if fname.split(".")[-1:][0] in excluded_extensions:
continue
if fname in excluded_files:
continue
hashvalues.append(_filehash(os.path.join(root, fname), hash_func))
if include_paths:
hasher = hash_func()
# get the resulting relative path into array of elements
path_list = os.path.relpath(os.path.join(root, fname)).split(os.sep)
# compute the hash on joined list, removes all os specific separators
hasher.update(''.join(path_list).encode('utf-8'))
hashvalues.append(hasher.hexdigest())
return _reduce_hash(hashvalues, hash_func)
def _filehash(filepath, hashfunc):
hasher = hashfunc()
blocksize = 64 * 1024
if not os.path.exists(filepath):
return hasher.hexdigest()
with open(filepath, "rb") as fp:
while True:
data = fp.read(blocksize)
if not data:
break
hasher.update(data)
return hasher.hexdigest()
def _reduce_hash(hashlist, hashfunc):
hasher = hashfunc()
for hashvalue in sorted(hashlist):
hasher.update(hashvalue.encode("utf-8"))
return hasher.hexdigest()

3
scripts/touch.bat Normal file
View File

@ -0,0 +1,3 @@
@echo off
type nul > %1
exit /b %errorlevel%

View File

@ -1,7 +1,6 @@
import glob
import os
import subprocess
import traceback
import shutil
from contextlib import contextmanager
@ -18,3 +17,13 @@ def pushd(new_dir):
def removeall(dir):
[os.remove(f) for f in glob.iglob("{}/*".format(dir), recursive=True)]
os.removedirs(dir)
def yeetdir(path):
os.makedirs(path, exist_ok=True)
shutil.rmtree(path)
def yeetfile(path):
if os.path.exists(path):
os.remove(path)

95
scripts/version.py Normal file
View File

@ -0,0 +1,95 @@
import os
import subprocess
import sys
from .log import *
from .utils import pushd
# Checks if the Orca tool should use a source checkout of Orca instead of a system install.
# This is copy-pasted to the command-line tool so it can work before loading anything.
#
# Returns: (use source, source directory, is actually the source's tool)
def check_if_source():
def path_is_in_orca_source(path):
dir = path
while True:
try:
os.stat(os.path.join(dir, ".orcaroot"))
return (True, dir)
except FileNotFoundError:
pass
newdir = os.path.dirname(dir)
if newdir == dir:
return (False, None)
dir = newdir
in_source, current_source_dir = path_is_in_orca_source(os.getcwd())
script_is_source, script_source_dir = path_is_in_orca_source(os.path.dirname(os.path.abspath(__file__)))
use_source = in_source or script_is_source
source_dir = current_source_dir or script_source_dir
return (use_source, source_dir, script_is_source)
def is_orca_source():
use_source, _, _ = check_if_source()
return use_source
def actual_install_dir():
# The path adjustment in here is technically sort of fragile because it depends
# on the current location of this actual file. But oh well.
if is_orca_source():
raise Exception("actual_install_dir should not be called when using the source version of the Orca tools")
return os.path.normpath(os.path.join(os.path.abspath(__file__), "../../.."))
def src_dir():
# More fragile path adjustments! Yay!
if is_orca_source():
return os.path.normpath(os.path.join(os.path.abspath(__file__), "../../src"))
else:
return os.path.normpath(os.path.join(os.path.abspath(__file__), "../../../src"))
def orca_version():
is_source, source_dir, _ = check_if_source()
if is_source:
with pushd(source_dir):
version = "unknown"
if os.path.exists(".git"):
try:
res = subprocess.run(["git", "rev-parse", "--short", "HEAD"], check=True, capture_output=True, text=True)
version = res.stdout.strip()
except subprocess.CalledProcessError:
log_warning("failed to look up current git hash for version number")
return f"dev-{version}"
else:
try:
with open(os.path.join(actual_install_dir(), ".orcaversion"), "r") as f:
version = f.read().strip()
return version
except FileNotFoundError:
return "dev-unknown"
def attach_version_command(subparsers):
version_cmd = subparsers.add_parser("version", help="Print the current Orca version.")
version_cmd.set_defaults(func=print_orca_version)
def print_orca_version(args):
use_source, source_dir, _ = check_if_source()
# This function prints the bare version number to stdout and everything else
# to stderr. This makes it easy to use the version number in shell pipelines
# without requiring extra flags or parsing a weird output format.
sys.stdout.write(orca_version() + "\n")
if use_source:
sys.stderr.write(f"Orca is running from a source checkout.\n")
sys.stderr.write(f"Source dir: {source_dir}\n")
else:
sys.stderr.write(f"Orca is running from a system installation.\n")
sys.stderr.write(f"Install dir: {actual_install_dir()}\n")

View File

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

View File

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 86 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Some files were not shown because too many files have changed in this diff Show More