Compare commits
4 commits
280688b615
...
e9ebc4457f
| Author | SHA1 | Date | |
|---|---|---|---|
| e9ebc4457f | |||
| 1075d4fff9 | |||
| f13054ee32 | |||
| 22ee3e232c |
6 changed files with 227 additions and 31 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1,4 +1,6 @@
|
|||
.zed/
|
||||
out/p2601*
|
||||
out/*.o
|
||||
thirdparty/zig*
|
||||
thirdparty/emsdk
|
||||
.DS_Store
|
||||
|
|
|
|||
90
do.ps1
90
do.ps1
|
|
@ -29,6 +29,7 @@ $EXE_NAME = "p2601";
|
|||
|
||||
function Get-Ext($platform) {
|
||||
if ($platform -eq "windows") { return ".exe"; }
|
||||
if ($platform -eq "emscripten") { return ".o"; }
|
||||
return "";
|
||||
}
|
||||
|
||||
|
|
@ -37,9 +38,14 @@ $ZIG_SLUG = "zig-${HOST_ARCH}-${HOST_OS}-${ZIG_VERSION}";
|
|||
$ZIG_DIR = Join-Path $DEPS_DIR $ZIG_SLUG
|
||||
$ZIG = Join-Path $ZIG_DIR "zig$(Get-Ext $HOST_OS)"
|
||||
|
||||
$BLOCKS_RT_DIR = Join-Path $DEPS_DIR "blocksruntime";
|
||||
$BLOCKS_RT_FLAGS = "-I$BLOCKS_RT_DIR -I$(Join-Path $BLOCKS_RT_DIR "BlocksRuntime")";
|
||||
$BLOCKS_RT_SOURCE = (Join-Path $BLOCKS_RT_DIR "BlocksRuntime" "runtime.c") + " " + (Join-Path $BLOCKS_RT_DIR "BlocksRuntime" "data.c");
|
||||
$BLOCKS_RT_DIR = Join-Path $DEPS_DIR "blocksruntime";
|
||||
$BLOCKS_RT_FLAGS = "-I$BLOCKS_RT_DIR -I$(Join-Path $BLOCKS_RT_DIR "BlocksRuntime")";
|
||||
$BLOCKS_RT_RUNTIME = (Join-Path $BLOCKS_RT_DIR "BlocksRuntime" "runtime.c");
|
||||
$BLOCKS_RT_DATA = (Join-Path $BLOCKS_RT_DIR "BlocksRuntime" "data.c");
|
||||
$BLOCKS_RT_SOURCE = "$BLOCKS_RT_RUNTIME $BLOCKS_RT_DATA";
|
||||
|
||||
$EMSDK_REPO = "https://github.com/emscripten-core/emsdk.git";
|
||||
$EMSDK_DIR = Join-Path $DEPS_DIR "emsdk";
|
||||
|
||||
$C_SOURCE = "src/main.c";
|
||||
$C_INCLUDES = "-Isrc -I$DEPS_DIR";
|
||||
|
|
@ -49,7 +55,7 @@ $RELEASE_FLAGS = "-Ofast -Wno-everything -ffast-math";
|
|||
$WINDOWS_FLAGS = "-ld3d11 -lgdi32";
|
||||
$MACOS_FLAGS = "-x objective-c -lobjc -framework Foundation -framework Cocoa -framework CoreFoundation -framework CoreGraphics -framework QuartzCore -framework Metal -framework MetalKit";
|
||||
$LINUX_FLAGS = "-lgl";
|
||||
|
||||
$WASM_FLAGS = "-c -fno-sanitize=address -fno-sanitize=undefined -isystem " + (Join-Path $EMSDK_DIR "upstream" "emscripten" "cache" "sysroot" "include");
|
||||
|
||||
# try vendoring zig
|
||||
if (-not (Test-Path $ZIG)) {
|
||||
|
|
@ -74,6 +80,21 @@ if (-not (Test-Path $ZIG)) {
|
|||
}
|
||||
}
|
||||
|
||||
# try vendoring emsdk
|
||||
if (-not (Test-Path $EMSDK_DIR)) {
|
||||
git clone $EMSDK_REPO $EMSDK_DIR
|
||||
|
||||
Set-Location $EMSDK_DIR
|
||||
|
||||
if ($IsWindows) {
|
||||
&"./emsdk.bat" install latest
|
||||
&"./emsdk.bat" activate latest
|
||||
} else {
|
||||
&"./emsdk" install latest
|
||||
&"./emsdk" activate latest
|
||||
}
|
||||
}
|
||||
|
||||
# ensure the out directory exists
|
||||
New-Item -ItemType Directory -Force -Path $OUT_DIR | Out-Null;
|
||||
|
||||
|
|
@ -92,6 +113,9 @@ function Get-Flags($os, $release) {
|
|||
"linux" {
|
||||
$flags += " $LINUX_FLAGS $BLOCKS_RT_FLAGS -DPLATFORM_LINUX";
|
||||
}
|
||||
"emscripten" {
|
||||
$flags += " $WASM_FLAGS $BLOCKS_RT_FLAGS -DPLATFORM_WASM -DPOINTER_32"
|
||||
}
|
||||
default {
|
||||
Write-Error "Unsupported operating system '$os'";
|
||||
}
|
||||
|
|
@ -117,6 +141,9 @@ function Get-Source($os) {
|
|||
"linux" {
|
||||
$source += " $BLOCKS_RT_SOURCE";
|
||||
}
|
||||
"emscripten" {
|
||||
$source += " $BLOCKS_RT_SOURCE"
|
||||
}
|
||||
default {
|
||||
Write-Error "Unsupported operating system '$os'";
|
||||
}
|
||||
|
|
@ -139,7 +166,7 @@ switch ($command) {
|
|||
|
||||
Write-Host (":: Compiling natively" + $(if ($release) { " (release mode)" } else { "" }));
|
||||
Write-Host $cmd;
|
||||
|
||||
|
||||
Invoke-Expression $cmd | Write-Host;
|
||||
}
|
||||
{($_ -eq "build-cross") -or ($_ -eq "bc")} {
|
||||
|
|
@ -152,12 +179,39 @@ switch ($command) {
|
|||
Write-Error "Unsupported target '$target' - run list-targets to see possible targets";
|
||||
}
|
||||
|
||||
$cmd = "$(CompileCommand $target_os $release) --target=$target -o $(Join-Path $OUT_DIR $($EXE_NAME + (Get-Ext $target_os)))";
|
||||
$out = Join-Path $OUT_DIR ($EXE_NAME + (Get-Ext $target_os));
|
||||
$cmd = "$(CompileCommand $target_os $release) --target=$target -o $out";
|
||||
|
||||
Write-Host (":: Cross-compiling for $target" + $(if ($release) { " (release mode)" } else { "" }));
|
||||
Write-Host $cmd;
|
||||
|
||||
|
||||
Invoke-Expression $cmd | Write-Host;
|
||||
|
||||
if ($target_os -eq "emscripten") {
|
||||
if (-not $IsWindows) {
|
||||
Set-Alias "python" "python3";
|
||||
}
|
||||
|
||||
[Environment]::SetEnvironmentVariable("EMSDK_QUIET", 1);
|
||||
& (Join-Path $EMSDK_DIR "emsdk_env.ps1");
|
||||
|
||||
$runtime_o = (Join-Path $OUT_DIR "p2601-blocks-runtime.o");
|
||||
$cmd = "$ZIG cc $WASM_FLAGS $BLOCKS_RT_FLAGS --target=$target -c $BLOCKS_RT_RUNTIME -o $runtime_o";
|
||||
|
||||
Write-Host $cmd;
|
||||
Invoke-Expression $cmd | Write-Host;
|
||||
|
||||
$data_o = (Join-Path $OUT_DIR "p2601-blocks-data.o");
|
||||
$cmd = "$ZIG cc $WASM_FLAGS $BLOCKS_RT_FLAGS --target=$target -c $BLOCKS_RT_DATA -o $data_O";
|
||||
|
||||
Write-Host $cmd;
|
||||
Invoke-Expression $cmd | Write-Host;
|
||||
|
||||
$binary = Join-Path $OUT_DIR ($EXE_NAME + (Get-Ext $HOST_OS));
|
||||
$cmd = "emcc $out $runtime_o $data_o -sUSE_WEBGL2=1 -sFULL_ES3=1 -sALLOW_MEMORY_GROWTH -o " + (Join-Path $OUT_DIR ($EXE_NAME + ".html"));
|
||||
Write-Host $cmd;
|
||||
Invoke-Expression $cmd | Write-Host;
|
||||
}
|
||||
}
|
||||
{($_ -eq "run") -or ($_ -eq "r")} {
|
||||
$release = $rest[0] -eq "release" -or $rest[0] -eq "fast";
|
||||
|
|
@ -166,26 +220,40 @@ switch ($command) {
|
|||
|
||||
Write-Host (":: Compiling natively" + $(if ($release) { " (release mode)" } else { "" }));
|
||||
Write-Host $cmd;
|
||||
|
||||
|
||||
Invoke-Expression $cmd | Write-Host;
|
||||
|
||||
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Invoke-Expression $binary | Write-Host;
|
||||
}
|
||||
}
|
||||
"run-wasm" {
|
||||
if (-not (Test-Path (Join-Path $OUT_DIR "p2601.wasm"))) {
|
||||
&"./do.ps1" build-cross wasm32-emscripten;
|
||||
}
|
||||
|
||||
$cmd = "$ZIG run " + (Join-Path $DEPS_DIR "tinyhttp.zig");
|
||||
Write-Host $cmd;
|
||||
Invoke-Expression $cmd | Write-Host;
|
||||
}
|
||||
{($_ -eq "clean") -or ($_ -eq "c")} {
|
||||
Write-Host ":: Cleaning up build artifacts...";
|
||||
Remove-Item -Path (Join-Path $OUT_DIR ($EXE_NAME + "*")) -Force;
|
||||
}
|
||||
{($_ -eq "list-targets") -or ($_ -eq "lt")} {
|
||||
# zig target doesn't actually output json...
|
||||
Write-Host ":: Available cross-compilation targets";
|
||||
Write-Host " x86_64-windows-gnu";
|
||||
Write-Host " x86_64-linux-gnu";
|
||||
Write-Host " wasm32-wasi";
|
||||
Write-Host " wasm32-freestanding";
|
||||
Write-Host " wasm32-emscripten";
|
||||
}
|
||||
default {
|
||||
Write-Host ":: Available things to do";
|
||||
Write-Host " build (b) compiles the program natively";
|
||||
Write-Host " build-cross (bc) <target> cross-compiles the program for the target triple (ex. x86_64-windows-gnu)";
|
||||
Write-Host " run (r) compiles and runs the native program";
|
||||
Write-Host " run-wasm compiles and runs the wasm program";
|
||||
Write-Host " clean (c) cleans up all build artifacts";
|
||||
Write-Host " list-targets (lt) lists all cross-compliation targets";
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ typedef closure(void*, arena__action, uword, uword, void*, const char*, sword) A
|
|||
#define $(a1, a2, a3, a4, a5, a6) ^void* (arena__action a1, uword a2, uword a3, void* a4, const char* a5, sword a6)
|
||||
|
||||
static Arena
|
||||
Static(uint8* data, uword count) {
|
||||
Static(u8* data, uword count) {
|
||||
memset(data, 0, count);
|
||||
|
||||
capture uword offset = 0;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#elifdef PLATFORM_LINUX
|
||||
#define SOKOL_GLES3
|
||||
#elifdef PLATFORM_WASM
|
||||
#define SOKOL_GLCORE
|
||||
#define SOKOL_GLES3
|
||||
#else
|
||||
#error "unsupported platform"
|
||||
#endif
|
||||
|
|
@ -145,8 +145,6 @@ event(const sapp_event* event) {
|
|||
|
||||
sapp_desc
|
||||
sokol_main(int argc, char* argv[]) {
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
return (sapp_desc) {
|
||||
.init_cb = init,
|
||||
.frame_cb = frame,
|
||||
|
|
@ -154,8 +152,8 @@ sokol_main(int argc, char* argv[]) {
|
|||
.event_cb = event,
|
||||
.logger.func = slog_func,
|
||||
|
||||
.width = 400,
|
||||
.height = 300,
|
||||
.width = 1280,
|
||||
.height = 720,
|
||||
.window_title = "hello, world",
|
||||
};
|
||||
}
|
||||
|
|
|
|||
40
thirdparty/blocksruntime/BlocksRuntime/runtime.c
vendored
40
thirdparty/blocksruntime/BlocksRuntime/runtime.c
vendored
|
|
@ -8,10 +8,10 @@
|
|||
* distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
* persons to whom the Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
|
|
@ -23,10 +23,23 @@
|
|||
*/
|
||||
|
||||
#include "Block_private.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef PLATFORM_WASM
|
||||
void* malloc(unsigned long s);
|
||||
void free(void* ptr);
|
||||
int printf_(const char*, ...);
|
||||
#define printf printf_
|
||||
int sprintf(char* restrict, const char* restrict, ...);
|
||||
#define memmove(a, b, c) __builtin_memmove(a, b, c)
|
||||
#define exit(a) do { if (a != 0) { __builtin_trap(); } } while (0)
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
|
|
@ -259,7 +272,7 @@ void _Block_use_GC5( void *(*alloc)(const unsigned long, const bool isOne, const
|
|||
_Block_use_GC(alloc, setHasRefcount, gc_assign, gc_assign_weak, _Block_memmove_gc_broken);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Called from objc-auto to alternatively turn on retain/release.
|
||||
* Prior to this the only "object" support we can provide is for those
|
||||
|
|
@ -286,10 +299,10 @@ static void *_Block_copy_internal(const void *arg, const int flags) {
|
|||
struct Block_layout *aBlock;
|
||||
const bool wantsOne = (WANTS_ONE & flags) == WANTS_ONE;
|
||||
|
||||
//printf("_Block_copy_internal(%p, %x)\n", arg, flags);
|
||||
//printf("_Block_copy_internal(%p, %x)\n", arg, flags);
|
||||
if (!arg) return NULL;
|
||||
|
||||
|
||||
|
||||
|
||||
// The following would be better done as a switch statement
|
||||
aBlock = (struct Block_layout *)arg;
|
||||
if (aBlock->flags & BLOCK_NEEDS_FREE) {
|
||||
|
|
@ -368,7 +381,7 @@ static void *_Block_copy_internal(const void *arg, const int flags) {
|
|||
static void _Block_byref_assign_copy(void *dest, const void *arg, const int flags) {
|
||||
struct Block_byref **destp = (struct Block_byref **)dest;
|
||||
struct Block_byref *src = (struct Block_byref *)arg;
|
||||
|
||||
|
||||
//printf("_Block_byref_assign_copy called, byref destp %p, src %p, flags %x\n", destp, src, flags);
|
||||
//printf("src dump: %s\n", _Block_byref_dump(src));
|
||||
if (src->forwarding->flags & BLOCK_IS_GC) {
|
||||
|
|
@ -417,7 +430,7 @@ static void _Block_byref_release(const void *arg) {
|
|||
|
||||
// dereference the forwarding pointer since the compiler isn't doing this anymore (ever?)
|
||||
shared_struct = shared_struct->forwarding;
|
||||
|
||||
|
||||
//printf("_Block_byref_release %p called, flags are %x\n", shared_struct, shared_struct->flags);
|
||||
// To support C++ destructors under GC we arrange for there to be a finalizer for this
|
||||
// by using an isa that directs the code to a finalizer that calls the byref_destroy method.
|
||||
|
|
@ -519,7 +532,7 @@ unsigned long int Block_size(void *arg) {
|
|||
#pragma mark Compiler SPI entry points
|
||||
#endif /* if 0 */
|
||||
|
||||
|
||||
|
||||
/*******************************************************
|
||||
|
||||
Entry points used by the compiler - the real API!
|
||||
|
|
@ -548,7 +561,7 @@ So the __block copy/dispose helpers will generate flag values of 3 or 7 for obje
|
|||
__weak block id 128+3+16
|
||||
__block (^Block) 128+7
|
||||
__weak __block (^Block) 128+7+16
|
||||
|
||||
|
||||
The implementation of the two routines would be improved by switch statements enumerating the eight cases.
|
||||
|
||||
********************************************************/
|
||||
|
|
@ -697,4 +710,3 @@ const char *_Block_byref_dump(struct Block_byref *src) {
|
|||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
|
|
|||
116
thirdparty/tinyhttp.zig
vendored
Normal file
116
thirdparty/tinyhttp.zig
vendored
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub fn main() !void {
|
||||
const addr = try std.net.Address.parseIp("0.0.0.0", 8080);
|
||||
var server = try addr.listen(.{ .reuse_address = true });
|
||||
defer server.deinit();
|
||||
|
||||
std.debug.print(":: Listening at http://localhost:8080\n", .{});
|
||||
|
||||
while (true) {
|
||||
const conn = server.accept() catch continue;
|
||||
defer conn.stream.close();
|
||||
handle_request(conn.stream) catch continue;
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_request(stream: std.net.Stream) !void {
|
||||
var req_buf: [4096]u8 = undefined;
|
||||
const n = try stream.read(&req_buf);
|
||||
if (n == 0) return error.Empty;
|
||||
|
||||
const request = req_buf[0..n];
|
||||
|
||||
// Parse "GET /path HTTP/1.x\r\n..."
|
||||
const path = blk: {
|
||||
if (!std.mem.startsWith(u8, request, "GET ")) return send_error(stream, "405 Method Not Allowed");
|
||||
const rest = request[4..];
|
||||
const end = std.mem.indexOfScalar(u8, rest, ' ') orelse return error.BadRequest;
|
||||
break :blk rest[0..end];
|
||||
};
|
||||
|
||||
const raw = if (std.mem.eql(u8, path, "/")) "/p2601.html" else path;
|
||||
|
||||
// Strip leading '/' and reject anything suspicious
|
||||
const rel = std.mem.trimLeft(u8, raw, "/");
|
||||
if (rel.len == 0 or
|
||||
std.mem.indexOf(u8, rel, "..") != null or
|
||||
std.mem.indexOfScalar(u8, rel, '\\') != null or
|
||||
rel[0] == '/')
|
||||
{
|
||||
return send_error(stream, "403 Forbidden");
|
||||
}
|
||||
|
||||
// Open from ./out/
|
||||
const dir = std.fs.cwd().openDir("out", .{}) catch return send_error(stream, "500 Internal Server Error");
|
||||
const file = dir.openFile(rel, .{}) catch return send_error(stream, "404 Not Found");
|
||||
defer file.close();
|
||||
|
||||
const stat = try file.stat();
|
||||
const size = stat.size;
|
||||
const mime = mime_from_path(rel);
|
||||
|
||||
// Send header
|
||||
var hdr_buf: [512]u8 = undefined;
|
||||
const header = std.fmt.bufPrint(&hdr_buf,
|
||||
"HTTP/1.1 200 OK\r\n" ++
|
||||
"Content-Type: {s}\r\n" ++
|
||||
"Content-Length: {d}\r\n" ++
|
||||
"Connection: close\r\n" ++
|
||||
"\r\n",
|
||||
.{ mime, size },
|
||||
) catch return error.HeaderTooLarge;
|
||||
|
||||
stream.writeAll(header) catch return;
|
||||
|
||||
// Stream the file in chunks
|
||||
var buf: [8192]u8 = undefined;
|
||||
while (true) {
|
||||
const bytes = file.read(&buf) catch return;
|
||||
if (bytes == 0) break;
|
||||
stream.writeAll(buf[0..bytes]) catch return;
|
||||
}
|
||||
}
|
||||
|
||||
fn send_error(stream: std.net.Stream, comptime status: []const u8) error{SendFailed} {
|
||||
const body = status;
|
||||
var hdr_buf: [256]u8 = undefined;
|
||||
const header = std.fmt.bufPrint(&hdr_buf,
|
||||
"HTTP/1.1 " ++ status ++ "\r\n" ++
|
||||
"Content-Type: text/plain\r\n" ++
|
||||
"Content-Length: {d}\r\n" ++
|
||||
"Connection: close\r\n" ++
|
||||
"\r\n",
|
||||
.{body.len},
|
||||
) catch return error.SendFailed;
|
||||
stream.writeAll(header) catch {};
|
||||
stream.writeAll(body) catch {};
|
||||
return error.SendFailed;
|
||||
}
|
||||
|
||||
fn mime_from_path(path: []const u8) []const u8 {
|
||||
const ext = std.fs.path.extension(path);
|
||||
const map = .{
|
||||
.{ ".html", "text/html;charset=utf-8" },
|
||||
.{ ".css", "text/css;charset=utf-8" },
|
||||
.{ ".js", "application/javascript;charset=utf-8" },
|
||||
.{ ".json", "application/json" },
|
||||
.{ ".png", "image/png" },
|
||||
.{ ".jpg", "image/jpeg" },
|
||||
.{ ".jpeg", "image/jpeg" },
|
||||
.{ ".gif", "image/gif" },
|
||||
.{ ".svg", "image/svg+xml" },
|
||||
.{ ".ico", "image/x-icon" },
|
||||
.{ ".woff", "font/woff" },
|
||||
.{ ".woff2", "font/woff2" },
|
||||
.{ ".ttf", "font/ttf" },
|
||||
.{ ".wasm", "application/wasm" },
|
||||
.{ ".pdf", "application/pdf" },
|
||||
.{ ".txt", "text/plain;charset=utf-8" },
|
||||
.{ ".xml", "application/xml" },
|
||||
};
|
||||
inline for (map) |entry| {
|
||||
if (std.mem.eql(u8, ext, entry[0])) return entry[1];
|
||||
}
|
||||
return "application/octet-stream";
|
||||
}
|
||||
Loading…
Reference in a new issue