Improvements for env handling with node.js and emscripten
- Initializes the environment so that getenv et al works properly - No longer calls JS functions at static init time; the JS preamble will pass the right env vars to ExecutionEnvironment - Sets the binary name to the path of the .js file
This commit is contained in:
parent
8a1159f4a7
commit
6452907b64
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* PANDA 3D SOFTWARE
|
||||
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
*
|
||||
* All use of this software is subject to the terms of the revised BSD
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file console_preamble.js
|
||||
* @author rdb
|
||||
* @date 2025-02-03
|
||||
*/
|
||||
|
||||
if (ENVIRONMENT_IS_NODE) {
|
||||
Module["preInit"] = Module["preInit"] || [];
|
||||
Module["preInit"].push(function() {
|
||||
if (typeof process === "object" && typeof process.env === "object") {
|
||||
// These are made up by emscripten if we don't set them to undefined
|
||||
ENV['USER'] = undefined;
|
||||
ENV['LOGNAME'] = undefined;
|
||||
ENV['PATH'] = undefined;
|
||||
ENV['PWD'] = undefined;
|
||||
ENV['HOME'] = undefined;
|
||||
ENV['LANG'] = undefined;
|
||||
ENV['_'] = undefined;
|
||||
for (var variable in process.env) {
|
||||
ENV[variable] = process.env[variable];
|
||||
}
|
||||
}
|
||||
|
||||
addOnPreMain(function preloadNodeEnv() {
|
||||
var sp = stackSave();
|
||||
var set_binary_name = wasmExports["_set_binary_name"];
|
||||
if (set_binary_name && typeof __filename === "string") {
|
||||
set_binary_name(stringToUTF8OnStack(__filename));
|
||||
}
|
||||
|
||||
var set_env_var = wasmExports["_set_env_var"];
|
||||
if (set_env_var) {
|
||||
for (var variable in ENV) {
|
||||
var value = ENV[variable];
|
||||
if (value !== undefined) {
|
||||
set_env_var(stringToUTF8OnStack(variable), stringToUTF8OnStack(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
stackRestore(sp);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -125,12 +125,18 @@ static const char *const libp3dtool_filenames[] = {
|
|||
|
||||
#if defined(__EMSCRIPTEN__) && !defined(CPPPARSER)
|
||||
extern "C" void EMSCRIPTEN_KEEPALIVE
|
||||
_set_env_var(ExecutionEnvironment *ptr, const char *var, const char *value) {
|
||||
_set_env_var(const char *var, const char *value) {
|
||||
ExecutionEnvironment *ptr = ExecutionEnvironment::get_ptr();
|
||||
ptr->_variables[std::string(var)] = std::string(value);
|
||||
}
|
||||
|
||||
extern "C" void EMSCRIPTEN_KEEPALIVE
|
||||
_set_binary_name(const char *path) {
|
||||
ExecutionEnvironment::set_binary_name(std::string(path));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Linux with GNU libc does have global argvargc variables, but we can't
|
||||
// Linux with GNU libc does have global argv/argc variables, but we can't
|
||||
// safely access them at stat init time--at least, not in libc5. (It does seem
|
||||
// to work with glibc2, however.)
|
||||
|
||||
|
|
@ -584,17 +590,10 @@ read_environment_variables() {
|
|||
}
|
||||
}
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
// We only have environment variables if we're running in node.js.
|
||||
#ifndef CPPPARSER
|
||||
EM_ASM({
|
||||
if (typeof process === 'object' && typeof process.env === 'object') {
|
||||
for (var variable in process.env) {
|
||||
__set_env_var($0, stringToUTF8OnStack(variable),
|
||||
stringToUTF8OnStack(process.env[variable]));
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
#endif
|
||||
// The environment variables get loaded in by the .js file before main()
|
||||
// using the _set_env_var exported function, defined above. Trying to load
|
||||
// env vars at static init time otherwise makes some optimizations more
|
||||
// difficult, notably wasm-ctor-eval/wizer.
|
||||
|
||||
#elif defined(HAVE_PROC_SELF_ENVIRON)
|
||||
// In some cases, we may have a file called procselfenviron that may be read
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@
|
|||
#include <map>
|
||||
|
||||
#if defined(__EMSCRIPTEN__) && !defined(CPPPARSER)
|
||||
class ExecutionEnvironment;
|
||||
|
||||
extern "C" void EMSCRIPTEN_KEEPALIVE
|
||||
_set_env_var(ExecutionEnvironment *ptr, const char *var, const char *value);
|
||||
_set_env_var(const char *var, const char *value);
|
||||
extern "C" void EMSCRIPTEN_KEEPALIVE
|
||||
_set_binary_name(const char *path);
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
@ -98,7 +98,7 @@ private:
|
|||
static ExecutionEnvironment *_global_ptr;
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
friend void ::_set_env_var(ExecutionEnvironment *ptr, const char *var, const char *value);
|
||||
friend void ::_set_env_var(const char *var, const char *value);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1913,6 +1913,9 @@ def CompileLink(dll, obj, opts):
|
|||
if GetOrigExt(dll) == ".exe":
|
||||
cmd += " -s EXIT_RUNTIME=1"
|
||||
|
||||
if dll.endswith(".js") and "SUBSYSTEM:WINDOWS" not in opts:
|
||||
cmd += " --pre-js dtool/src/dtoolutil/console_preamble.js"
|
||||
|
||||
else:
|
||||
cmd += " -pthread"
|
||||
if "SYSROOT" in SDK:
|
||||
|
|
@ -5984,7 +5987,7 @@ if GetLinkAllStatic():
|
|||
if not PkgSkip('BULLET'):
|
||||
DefSymbol('RUN_TESTS_FLAGS', 'HAVE_BULLET')
|
||||
|
||||
OPTS=['DIR:tests', 'PYTHON', 'RUN_TESTS_FLAGS']
|
||||
OPTS=['DIR:tests', 'PYTHON', 'RUN_TESTS_FLAGS', 'SUBSYSTEM:CONSOLE']
|
||||
PyTargetAdd('run_tests-main.obj', opts=OPTS, input='main.c')
|
||||
PyTargetAdd('run_tests.exe', input='run_tests-main.obj')
|
||||
PyTargetAdd('run_tests.exe', input='core.pyd')
|
||||
|
|
|
|||
42
tests/main.c
42
tests/main.c
|
|
@ -19,11 +19,6 @@
|
|||
|
||||
#include <Python.h>
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten/emscripten.h>
|
||||
#include <emscripten/em_asm.h>
|
||||
#endif
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#ifdef LINK_ALL_STATIC
|
||||
|
|
@ -55,43 +50,6 @@ int main(int argc, char **argv) {
|
|||
PyConfig config;
|
||||
PyConfig_InitPythonConfig(&config);
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
// getenv does not work with emscripten, instead read the PYTHONPATH and
|
||||
// PYTHONHOME from the process.env variable if we're running in node.js.
|
||||
char path[4096], home[4096];
|
||||
path[0] = 0;
|
||||
home[0] = 0;
|
||||
|
||||
EM_ASM({
|
||||
if (typeof process === 'object' && typeof process.env === 'object') {
|
||||
var path = process.env.PYTHONPATH;
|
||||
var home = process.env.PYTHONHOME;
|
||||
if (path) {
|
||||
if (process.platform === 'win32') {
|
||||
path = path.replace(/;/g, ':');
|
||||
}
|
||||
stringToUTF8(path, $0, $1);
|
||||
}
|
||||
if (home) {
|
||||
stringToUTF8(home, $2, $3);
|
||||
}
|
||||
}
|
||||
}, path, sizeof(path), home, sizeof(home));
|
||||
|
||||
if (path[0] != 0) {
|
||||
status = PyConfig_SetBytesString(&config, &config.pythonpath_env, path);
|
||||
if (PyStatus_Exception(status)) {
|
||||
goto exception;
|
||||
}
|
||||
}
|
||||
if (home[0] != 0) {
|
||||
status = PyConfig_SetBytesString(&config, &config.home, home);
|
||||
if (PyStatus_Exception(status)) {
|
||||
goto exception;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
PyConfig_SetBytesString(&config, &config.run_module, "pytest");
|
||||
config.parse_argv = 0;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue