mirror of
https://github.com/The-Powder-Toy/The-Powder-Toy.git
synced 2025-08-15 04:44:00 +02:00
Add run-target serve-locally to emscripten builds
Invoke with: ninja serve-locally Also fix emscripten builds on some systems where emscripten suddenly needs USE_PTHREADS (?????). Also fix JS-unsafe app_exe values breaking builds.
This commit is contained in:
21
meson.build
21
meson.build
@@ -202,6 +202,7 @@ project_cpp_args = []
|
|||||||
fftw_dep = dependency('fftw3f', static: is_static)
|
fftw_dep = dependency('fftw3f', static: is_static)
|
||||||
threads_dep = dependency('threads')
|
threads_dep = dependency('threads')
|
||||||
if host_platform == 'emscripten'
|
if host_platform == 'emscripten'
|
||||||
|
app_exe_jssafe = app_exe.underscorify()
|
||||||
zlib_dep = []
|
zlib_dep = []
|
||||||
png_dep = []
|
png_dep = []
|
||||||
sdl2_dep = []
|
sdl2_dep = []
|
||||||
@@ -215,19 +216,20 @@ if host_platform == 'emscripten'
|
|||||||
'-s', 'EXPORTED_RUNTIME_METHODS=ccall,cwrap',
|
'-s', 'EXPORTED_RUNTIME_METHODS=ccall,cwrap',
|
||||||
'-s', 'FS_DEBUG',
|
'-s', 'FS_DEBUG',
|
||||||
'-s', 'MODULARIZE',
|
'-s', 'MODULARIZE',
|
||||||
'-s', 'EXPORT_NAME=create_' + app_exe,
|
'-s', 'EXPORT_NAME=create_' + app_exe_jssafe,
|
||||||
'-Wl,-u,_emscripten_run_callback_on_thread',
|
'-Wl,-u,_emscripten_run_callback_on_thread',
|
||||||
'-lidbfs.js',
|
'-lidbfs.js',
|
||||||
|
'--source-map-base=./',
|
||||||
]
|
]
|
||||||
emcc_args = [
|
emcc_args = [
|
||||||
'-s', 'USE_SDL=2',
|
'-s', 'USE_SDL=2',
|
||||||
'-s', 'USE_BZIP2=1',
|
'-s', 'USE_BZIP2=1',
|
||||||
'-s', 'USE_LIBPNG',
|
'-s', 'USE_LIBPNG',
|
||||||
|
'-s', 'USE_PTHREADS',
|
||||||
'-s', 'USE_ZLIB=1',
|
'-s', 'USE_ZLIB=1',
|
||||||
'-s', 'DISABLE_EXCEPTION_CATCHING=0',
|
'-s', 'DISABLE_EXCEPTION_CATCHING=0',
|
||||||
|
'-gsource-map',
|
||||||
]
|
]
|
||||||
project_link_args += [ '--source-map-base=./' ]
|
|
||||||
emcc_args += [ '-gsource-map' ]
|
|
||||||
project_link_args += emcc_args
|
project_link_args += emcc_args
|
||||||
project_cpp_args += emcc_args
|
project_cpp_args += emcc_args
|
||||||
else
|
else
|
||||||
@@ -542,7 +544,7 @@ if get_option('build_powder')
|
|||||||
)
|
)
|
||||||
subdir('android')
|
subdir('android')
|
||||||
else
|
else
|
||||||
executable(
|
powder_exe = executable(
|
||||||
app_exe,
|
app_exe,
|
||||||
sources: powder_files,
|
sources: powder_files,
|
||||||
include_directories: project_inc,
|
include_directories: project_inc,
|
||||||
@@ -623,3 +625,14 @@ if get_option('clang_tidy')
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if host_platform == 'emscripten'
|
||||||
|
run_target(
|
||||||
|
'serve-locally',
|
||||||
|
command: [
|
||||||
|
python3_prog,
|
||||||
|
serve_wasm_py,
|
||||||
|
],
|
||||||
|
depends: powder_exe,
|
||||||
|
)
|
||||||
|
endif
|
||||||
|
@@ -115,6 +115,16 @@ elif host_platform == 'linux'
|
|||||||
output: 'appdata.xml',
|
output: 'appdata.xml',
|
||||||
configuration: conf_data,
|
configuration: conf_data,
|
||||||
)
|
)
|
||||||
|
elif host_platform == 'emscripten'
|
||||||
|
servewasm_conf_data = configuration_data()
|
||||||
|
servewasm_conf_data.set('SERVER', server)
|
||||||
|
servewasm_conf_data.set('APP_EXE', app_exe)
|
||||||
|
servewasm_conf_data.set('APP_EXE_JSSAFE', app_exe_jssafe)
|
||||||
|
serve_wasm_py = configure_file(
|
||||||
|
input: 'serve-wasm.template.py',
|
||||||
|
output: 'serve-wasm.py',
|
||||||
|
configuration: servewasm_conf_data,
|
||||||
|
)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
embedded_files += [
|
embedded_files += [
|
||||||
|
120
resources/serve-wasm.template.py
Normal file
120
resources/serve-wasm.template.py
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
from OpenSSL import crypto
|
||||||
|
import http.server
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import ssl
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
HTTP_HOST = '127.0.0.1'
|
||||||
|
HTTP_PORT = 8000
|
||||||
|
HTTP_INDEX = 'serve-wasm.index.html'
|
||||||
|
KEY_FILE = 'serve-wasm.key.pem'
|
||||||
|
CERT_FILE = 'serve-wasm.cert.crt'
|
||||||
|
CERT_CN = 'serve-wasm.py self-signed certificate for @APP_EXE@.js'
|
||||||
|
CERT_TTL = 30 * 24 * 60 * 60
|
||||||
|
|
||||||
|
print(f'generating index for @APP_EXE@.js')
|
||||||
|
with open(HTTP_INDEX, 'wt') as f:
|
||||||
|
f.write(f'''
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<body>
|
||||||
|
<p>Remember, this is being served locally, so it will not be able to connect to <a href="@SERVER@">@SERVER@</a>. To enable this, serve the following files there:</p>
|
||||||
|
<ul>
|
||||||
|
<li>@APP_EXE@.js</li>
|
||||||
|
<li>@APP_EXE@.wasm</li>
|
||||||
|
<li>@APP_EXE@.wasm.map for debugging purposes</li>
|
||||||
|
</ul>
|
||||||
|
<p id="status" style="display: none;">Loading...</p>
|
||||||
|
<canvas style="display: none;" class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" tabindex=-1></canvas>
|
||||||
|
<script type='text/javascript'>
|
||||||
|
(() => {{
|
||||||
|
var promise;
|
||||||
|
|
||||||
|
window.create_@APP_EXE_JSSAFE@_loader = () => {{
|
||||||
|
if (promise === undefined) {{
|
||||||
|
promise = new Promise((resolve, reject) => {{
|
||||||
|
const script = document.createElement('script');
|
||||||
|
script.onload = () => {{
|
||||||
|
resolve(window.create_@APP_EXE_JSSAFE@);
|
||||||
|
}};
|
||||||
|
document.head.appendChild(script);
|
||||||
|
script.src = '@APP_EXE@.js';
|
||||||
|
}});
|
||||||
|
}}
|
||||||
|
return promise;
|
||||||
|
}};
|
||||||
|
}})();
|
||||||
|
(() => {{
|
||||||
|
var canvas = document.getElementById('canvas');
|
||||||
|
var status = document.getElementById('status');
|
||||||
|
window.mark_presentable = function() {{
|
||||||
|
canvas.style.display = 'initial';
|
||||||
|
}};
|
||||||
|
window.onerror = (event) => {{
|
||||||
|
status.innerText = 'Exception thrown, see JavaScript console';
|
||||||
|
status.style.display = 'initial';
|
||||||
|
}};
|
||||||
|
create_@APP_EXE_JSSAFE@_loader().then(create_@APP_EXE_JSSAFE@ => create_@APP_EXE_JSSAFE@({{
|
||||||
|
canvas: (() => {{
|
||||||
|
canvas.addEventListener('webglcontextlost', e => {{
|
||||||
|
alert('WebGL context lost. You will need to reload the page.'); e.preventDefault();
|
||||||
|
}}, false);
|
||||||
|
return canvas;
|
||||||
|
}})(),
|
||||||
|
print: console.log,
|
||||||
|
printErr: console.log,
|
||||||
|
}}));
|
||||||
|
}})();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
''')
|
||||||
|
|
||||||
|
def remove_if_too_old(path):
|
||||||
|
if os.path.isfile(path):
|
||||||
|
diff = time.time() - os.path.getmtime(path)
|
||||||
|
if diff > CERT_TTL / 2:
|
||||||
|
os.remove(path)
|
||||||
|
|
||||||
|
remove_if_too_old(CERT_FILE)
|
||||||
|
remove_if_too_old(KEY_FILE)
|
||||||
|
|
||||||
|
if not (os.path.isfile(CERT_FILE) and os.path.isfile(KEY_FILE)):
|
||||||
|
print('generating keypair')
|
||||||
|
key = crypto.PKey()
|
||||||
|
key.generate_key(crypto.TYPE_RSA, 2048)
|
||||||
|
cert = crypto.X509()
|
||||||
|
cert.get_subject().CN = CERT_CN
|
||||||
|
cert.set_serial_number(int(time.time()))
|
||||||
|
cert.gmtime_adj_notBefore(0)
|
||||||
|
cert.gmtime_adj_notAfter(CERT_TTL)
|
||||||
|
cert.set_issuer(cert.get_subject())
|
||||||
|
cert.set_pubkey(key)
|
||||||
|
cert.sign(key, 'sha256')
|
||||||
|
with open(CERT_FILE, 'wt') as f:
|
||||||
|
f.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert).decode('utf-8'))
|
||||||
|
with open(KEY_FILE, 'wt') as f:
|
||||||
|
f.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, key).decode('utf-8'))
|
||||||
|
|
||||||
|
class MyHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
|
||||||
|
index_pages = (HTTP_INDEX, )
|
||||||
|
|
||||||
|
def end_headers(self):
|
||||||
|
print(self.index_pages)
|
||||||
|
self.send_my_headers()
|
||||||
|
http.server.SimpleHTTPRequestHandler.end_headers(self)
|
||||||
|
|
||||||
|
def send_my_headers(self):
|
||||||
|
self.send_header('Cross-Origin-Opener-Policy', 'same-origin')
|
||||||
|
self.send_header('Cross-Origin-Embedder-Policy', 'require-corp')
|
||||||
|
|
||||||
|
server_address = (HTTP_HOST, HTTP_PORT)
|
||||||
|
httpd = http.server.HTTPServer(server_address, MyHTTPRequestHandler)
|
||||||
|
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
|
||||||
|
ssl_context.load_cert_chain(certfile=CERT_FILE, keyfile=KEY_FILE)
|
||||||
|
httpd.socket = ssl_context.wrap_socket(httpd.socket, server_side=True)
|
||||||
|
print(f'serving at https://{HTTP_HOST}:{HTTP_PORT}, Ctrl+C to exit')
|
||||||
|
httpd.serve_forever()
|
Reference in New Issue
Block a user