fixed linking
This commit is contained in:
@@ -117,6 +117,8 @@ if host_machine.system() != 'emscripten'
|
||||
endif
|
||||
endif
|
||||
|
||||
link += '-rdynamic'
|
||||
|
||||
link_args = link
|
||||
sources = []
|
||||
src += [ # core
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var cellfs = this
|
||||
var cellfs = {}
|
||||
|
||||
// CellFS: A filesystem implementation using miniz and raw OS filesystem
|
||||
// Supports mounting multiple sources (fs, zip) and named mounts (@name)
|
||||
@@ -456,10 +456,6 @@ function globfs(globs, dir) {
|
||||
return results
|
||||
}
|
||||
|
||||
function slurp(path) {
|
||||
return slurp(path)
|
||||
}
|
||||
|
||||
// Exports
|
||||
cellfs.mount = mount
|
||||
cellfs.mount_package = mount_package
|
||||
@@ -483,4 +479,6 @@ cellfs.slurp = slurp
|
||||
|
||||
cellfs.mount('.')
|
||||
|
||||
log.console(`about to return...`)
|
||||
|
||||
return cellfs
|
||||
|
||||
@@ -49,7 +49,7 @@ JSC_SSCALL(os_eval,
|
||||
JSC_SSCALL(js_compile,
|
||||
if (!str2) return JS_ThrowReferenceError(js, "Second argument should be the script.");
|
||||
if (!str) return JS_ThrowReferenceError(js, "First argument should be the name of the script.");
|
||||
ret = JS_Eval(js, str2, strlen(str2), str, JS_EVAL_FLAG_COMPILE_ONLY);
|
||||
ret = JS_Eval(js, str2, strlen(str2), str, JS_EVAL_FLAG_COMPILE_ONLY | JS_EVAL_FLAG_BACKTRACE_BARRIER);
|
||||
)
|
||||
|
||||
// Evaluate a function object in the current QuickJS context.
|
||||
|
||||
@@ -188,8 +188,9 @@ static JSValue js_qop_read(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
qop_file *file = qop_find(qop, path);
|
||||
JS_FreeCString(js, path);
|
||||
|
||||
if (!file)
|
||||
if (!file) {
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
unsigned char *dest = js_malloc(js, file->size);
|
||||
if (!dest)
|
||||
|
||||
@@ -7,6 +7,7 @@ var time = use('time')
|
||||
var js = use('js')
|
||||
var crypto = use('crypto')
|
||||
var utf8 = use('utf8')
|
||||
var blob = use('blob')
|
||||
var qop
|
||||
var core_qop
|
||||
|
||||
@@ -137,16 +138,13 @@ function ensure_dir(path) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Load cell.toml configuration
|
||||
// module given in canonical format (e.g., "gitea.pockle.world/john/prosperon")
|
||||
// If module is null, loads the root cell.toml
|
||||
// If module is provided, loads module/cell.toml
|
||||
Shop.load_config = function(module) {
|
||||
log.console(`checking for config ${module}`)
|
||||
var content
|
||||
if (!module) {
|
||||
if (!fd.is_file(shop_path))
|
||||
return null
|
||||
|
||||
log.console(`found config ${shop_path}`)
|
||||
content = fd.slurp(shop_path)
|
||||
} else {
|
||||
var module_path = `.cell/modules/${module}/.cell/cell.toml`
|
||||
@@ -156,6 +154,13 @@ Shop.load_config = function(module) {
|
||||
content = fd.slurp(module_path)
|
||||
}
|
||||
|
||||
if (!(content instanceof blob)) {
|
||||
log.console(`critical error`)
|
||||
for (var k in content)
|
||||
log.console(k)
|
||||
throw new Error("fucked up bad")
|
||||
}
|
||||
|
||||
if (!content.length) return {}
|
||||
var cfg = toml.decode(text(content))
|
||||
if (cfg.dependencies) {
|
||||
@@ -175,9 +180,6 @@ Shop.load_config = function(module) {
|
||||
}
|
||||
}
|
||||
|
||||
// If we modified dependencies and this is the root config, save it back
|
||||
// But load_config is also called for modules (which we can't write to easily/shouldn't)
|
||||
// So we only save if module is null (root config)
|
||||
if (changed && !module) {
|
||||
Shop.save_config(cfg)
|
||||
}
|
||||
@@ -491,7 +493,8 @@ var script_forms = []
|
||||
|
||||
script_forms['.cm'] = function(path, script, pkg) {
|
||||
var pkg_arg = pkg ? `'${pkg}'` : 'null'
|
||||
var fn = `(function setup_module($_){ var use = function(path) { return globalThis.use(path, ${pkg_arg}); }; ${script}})`
|
||||
var relative_use_fn = `def use = function(path) { return globalThis.use(path, ${pkg_arg});}`
|
||||
var fn = `(function setup_module($_){ ${relative_use_fn}; ${script}})`
|
||||
return fn
|
||||
}
|
||||
|
||||
@@ -575,7 +578,7 @@ function resolve_locator(path, ext, ctx)
|
||||
}
|
||||
|
||||
var core = core_qop.read(path + ext)
|
||||
if (core) {
|
||||
if (core != null) {
|
||||
var form = script_forms[ext]
|
||||
if (!form) throw new Error(`No script form for extension ${ext}`)
|
||||
var script = form(null,text(core))
|
||||
@@ -592,10 +595,26 @@ function resolve_c_symbol(path, package_context)
|
||||
var local_sym_base = path.replace(/\//g, '_').replace(/-/g, '_').replace(/\./g, '_')
|
||||
var local
|
||||
|
||||
function symbolify_path(p) {
|
||||
return p.replace(/\//g, '_').replace(/-/g, '_').replace(/\./g, '_')
|
||||
}
|
||||
|
||||
function symbol_candidates(pkg_path, mod_sym) {
|
||||
var variants = []
|
||||
var paths = [pkg_path]
|
||||
if (!pkg_path.startsWith('/')) paths.push('/' + pkg_path)
|
||||
for (var i = 0; i < paths.length; i++) {
|
||||
var candidate = `js_${symbolify_path(paths[i])}_${mod_sym}_use`
|
||||
if (variants.indexOf(candidate) < 0)
|
||||
variants.push(candidate)
|
||||
}
|
||||
return variants
|
||||
}
|
||||
|
||||
if (!package_context) {
|
||||
local = `js_local_${local_sym_base}_use`
|
||||
} else {
|
||||
local = `js_${local_path.replace(/\//g, '_').replace(/-/g, '_').replace(/\./g, '_')}_${local_sym_base}_use`
|
||||
local = null // handled via candidates below
|
||||
}
|
||||
|
||||
var build_dir = get_build_dir(package_context)
|
||||
@@ -606,20 +625,28 @@ function resolve_c_symbol(path, package_context)
|
||||
open_dls[local_dl_name] = os.dylib_open(local_dl_name);
|
||||
|
||||
if (open_dls[local_dl_name]) {
|
||||
if (os.dylib_has_symbol(open_dls[local_dl_name], local))
|
||||
var locals = package_context ? symbol_candidates(local_path, local_sym_base) : [local]
|
||||
for (var i = 0; i < locals.length; i++) {
|
||||
var candidate = locals[i]
|
||||
if (os.dylib_has_symbol(open_dls[local_dl_name], candidate))
|
||||
return {
|
||||
symbol: function() { return os.dylib_symbol(open_dls[local_dl_name], local); },
|
||||
symbol: function() { return os.dylib_symbol(open_dls[local_dl_name], candidate); },
|
||||
scope: SCOPE_LOCAL
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try static linking fallback
|
||||
if (os.internal_exists(local))
|
||||
var local_candidates = package_context ? symbol_candidates(local_path, local_sym_base) : [local]
|
||||
for (var li = 0; li < local_candidates.length; li++) {
|
||||
var lc = local_candidates[li]
|
||||
if (os.internal_exists(lc))
|
||||
return {
|
||||
symbol: function() { return os.load_internal(local); },
|
||||
symbol: function() { return os.load_internal(lc); },
|
||||
scope: SCOPE_LOCAL
|
||||
};
|
||||
}
|
||||
|
||||
// If 'path' has a package alias (e.g. 'prosperon/sprite'), try to resolve it
|
||||
var pkg_alias = get_import_package(path)
|
||||
@@ -630,14 +657,13 @@ function resolve_c_symbol(path, package_context)
|
||||
var dl_path = build_dir + '/cellmod' + dylib_ext
|
||||
var mod_name = get_import_name(path)
|
||||
var mod_sym = mod_name.replace(/\//g, '_').replace(/-/g, '_').replace(/\./g, '_')
|
||||
|
||||
var pkg_safe = canon_pkg.replace(/\//g, '_').replace(/-/g, '_').replace(/\./g, '_')
|
||||
var sym_name = `js_${pkg_safe}_${mod_sym}_use`
|
||||
log.console(`looking for ${sym_name}`)
|
||||
var sym_names = symbol_candidates(canon_pkg, mod_sym)
|
||||
|
||||
if (fd.is_file(dl_path)) {
|
||||
if (!open_dls[dl_path]) open_dls[dl_path] = os.dylib_open(dl_path)
|
||||
if (open_dls[dl_path]) {
|
||||
for (var si = 0; si < sym_names.length; si++) {
|
||||
var sym_name = sym_names[si]
|
||||
if (os.dylib_has_symbol(open_dls[dl_path], sym_name))
|
||||
return {
|
||||
symbol: function() { return os.dylib_symbol(open_dls[dl_path], sym_name) },
|
||||
@@ -646,7 +672,10 @@ function resolve_c_symbol(path, package_context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var sii = 0; sii < sym_names.length; sii++) {
|
||||
var sym_name = sym_names[sii]
|
||||
if (os.internal_exists(sym_name))
|
||||
return {
|
||||
symbol: function() { return os.load_internal(sym_name) },
|
||||
@@ -655,6 +684,7 @@ function resolve_c_symbol(path, package_context)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var core_sym = `js_${path.replace(/\//g, '_')}_use`;
|
||||
if (os.internal_exists(core_sym))
|
||||
@@ -674,8 +704,6 @@ Shop.use = function(path, package_context) {
|
||||
var c_resolve = resolve_c_symbol(path, package_context) || {scope:999}
|
||||
var mod_resolve = resolve_locator(path, '.cm', package_context) || {scope:999}
|
||||
|
||||
log.console(`c_resolve: ${json.encode(c_resolve)}, mod_resolve: ${json.encode(mod_resolve)} for ${path} in package ${package_context}`)
|
||||
|
||||
var min_scope = Math.min(c_resolve.scope, mod_resolve.scope)
|
||||
|
||||
if (min_scope == 999)
|
||||
@@ -686,14 +714,20 @@ Shop.use = function(path, package_context) {
|
||||
if (use_cache[cache_key])
|
||||
return use_cache[cache_key]
|
||||
|
||||
if (c_resolve.scope < mod_resolve.scope)
|
||||
use_cache[cache_key] = c_resolve.symbol()
|
||||
else if (mod_resolve.scope < c_resolve.scope)
|
||||
use_cache[cache_key] = mod_resolve.symbol.call()
|
||||
else
|
||||
use_cache[cache_key] = mod_resolve.symbol.call(c_resolve.symbol())
|
||||
var used
|
||||
|
||||
return use_cache[cache_key]
|
||||
if (c_resolve.scope < mod_resolve.scope)
|
||||
used = c_resolve.symbol()
|
||||
else if (mod_resolve.scope < c_resolve.scope)
|
||||
used = mod_resolve.symbol.call()
|
||||
else
|
||||
used = mod_resolve.symbol.call(c_resolve.symbol())
|
||||
|
||||
if (!used)
|
||||
throw new Error(`Module ${path} via package ${package_context} returned null`)
|
||||
|
||||
use_cache[cache_key] = used
|
||||
return used
|
||||
}
|
||||
|
||||
Shop.resolve_locator = resolve_locator
|
||||
@@ -1117,6 +1151,7 @@ Shop.build_package = function(package)
|
||||
resolve_mod_fn(src_path, package)
|
||||
} catch (e) {
|
||||
log.error(`Failed to compile ${src_path}: ${e}`)
|
||||
log.error(e)
|
||||
return false
|
||||
}
|
||||
} else if (file.endsWith('.c') || file.endsWith('.cpp')) {
|
||||
@@ -1175,8 +1210,8 @@ Shop.build_package = function(package)
|
||||
if (needs_link) {
|
||||
log.console("Linking " + lib_name)
|
||||
|
||||
var link_flags = '-shared'
|
||||
if (platform == 'macOS') link_flags = '-shared -undefined dynamic_lookup'
|
||||
var link_flags = '-fPIC -shared'
|
||||
if (platform == 'macOS') link_flags += ' -undefined dynamic_lookup'
|
||||
|
||||
var ldflags = get_flags(config, platform, 'LDFLAGS')
|
||||
if (ldflags != '') link_flags += ' ' + ldflags
|
||||
@@ -1187,7 +1222,7 @@ Shop.build_package = function(package)
|
||||
objs_str += '"$HERE/' + c_objects[i] + '" '
|
||||
}
|
||||
|
||||
var link_cmd = 'HERE=$(pwd); cd ' + module_dir + ' && cc ' + link_flags + ' ' + objs_str + ' -lcell -lc -lc++ -o ' + temp_lib
|
||||
var link_cmd = 'HERE=$(pwd); cd ' + module_dir + ' && cc ' + link_flags + ' ' + objs_str + ' -lc -lc++ -o ' + temp_lib
|
||||
var ret = os.system(link_cmd)
|
||||
if (ret != 0) {
|
||||
log.error("Linking failed")
|
||||
|
||||
@@ -14,4 +14,6 @@ for (var pack of packages) {
|
||||
shop.build_package(pack)
|
||||
}
|
||||
|
||||
shop.build_package()
|
||||
|
||||
$_.stop()
|
||||
@@ -161,11 +161,6 @@ JSValue TYPE##2js(JSContext *js, TYPE *n) { \
|
||||
return j; }\
|
||||
\
|
||||
|
||||
#define QJSGLOBALCLASS(NAME) \
|
||||
JSValue NAME = JS_NewObject(js); \
|
||||
JS_SetPropertyFunctionList(js, NAME, js_##NAME##_funcs, countof(js_##NAME##_funcs)); \
|
||||
JS_SetPropertyStr(js, globalThis, #NAME, NAME); \
|
||||
|
||||
/* Defines a class and uses its function list as its prototype */
|
||||
#define QJSCLASSPREP_FUNCS(TYPE) \
|
||||
QJSCLASSPREP_NO_FUNCS(TYPE) \
|
||||
@@ -173,10 +168,19 @@ JS_SetPropertyFunctionList(js, TYPE##_proto, js_##TYPE##_funcs, countof(js_##TYP
|
||||
|
||||
#define QJSCLASSPREP_NO_FUNCS(TYPE) \
|
||||
JS_NewClassID(&js_##TYPE##_id);\
|
||||
printf(" class %s got new id %d\n", #TYPE, js_##TYPE##_id);\
|
||||
JS_NewClass(JS_GetRuntime(js), js_##TYPE##_id, &js_##TYPE##_class);\
|
||||
JSValue TYPE##_proto = JS_NewObject(js); \
|
||||
JS_SetClassProto(js, js_##TYPE##_id, TYPE##_proto); \
|
||||
|
||||
#define QJSCLASSPREP_FUNCS_CTOR(TYPE, CTOR_ARGC) \
|
||||
({ \
|
||||
QJSCLASSPREP_FUNCS(TYPE); \
|
||||
JSValue TYPE##_ctor = JS_NewCFunction2(js, js_##TYPE##_constructor, #TYPE, CTOR_ARGC, JS_CFUNC_constructor, 0); \
|
||||
JS_SetConstructor(js, TYPE##_ctor, TYPE##_proto); \
|
||||
TYPE##_ctor; \
|
||||
})
|
||||
|
||||
|
||||
#define countof(x) (sizeof(x)/sizeof((x)[0]))
|
||||
|
||||
|
||||
@@ -488,24 +488,8 @@ static const JSCFunctionListEntry js_blob_funcs[] = {
|
||||
JS_CGETSET_DEF("length", js_blob_get_length, NULL),
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// js_blob_use(ctx) for easy embedding: returns an object with the blob functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
JSValue js_blob_use(JSContext *js) {
|
||||
// Register the blob class
|
||||
QJSCLASSPREP_FUNCS(blob);
|
||||
|
||||
// Create the constructor function
|
||||
JSValue ctor = JS_NewCFunction2(js, js_blob_constructor, "blob", 3, JS_CFUNC_constructor, 0);
|
||||
|
||||
// Set the prototype on the constructor
|
||||
JSValue proto = JS_GetClassProto(js, js_blob_id);
|
||||
JS_SetConstructor(js, ctor, proto);
|
||||
// Explicitly set the prototype property to ensure instanceof works
|
||||
JS_SetPropertyStr(js, ctor, "__prototype__", JS_DupValue(js, proto));
|
||||
JS_FreeValue(js, proto);
|
||||
return ctor;
|
||||
return QJSCLASSPREP_FUNCS_CTOR(blob, 3);
|
||||
}
|
||||
|
||||
JSValue js_new_blob_stoned_copy(JSContext *js, void *data, size_t bytes)
|
||||
|
||||
Reference in New Issue
Block a user