File System Emulation

I'm trying to get a file system emulation POC going. https://docs.leaningtech.com/cheerp/Filesystem-emulation The core of my new code for this is as simple as that doc page:
[[cheerp::genericjs]]
void preloadCallback()
{
// Files are ready
//Window *fd = open("assets/tstcweb.scr");
client::console.log("Hello, files loaded.");
//client::console.log(fd);
}

cheerp::FilePreloader files(preloadCallback, "tstcweb.scr");
[[cheerp::genericjs]]
void preloadCallback()
{
// Files are ready
//Window *fd = open("assets/tstcweb.scr");
client::console.log("Hello, files loaded.");
//client::console.log(fd);
}

cheerp::FilePreloader files(preloadCallback, "tstcweb.scr");
I get this in the browser js console:
Uncaught (in promise) Error: this should be unreachable

__dummy http://localhost:8000/xlink_cheerp_wasm.js:271

__start http://localhost:8000/xlink_cheerp_wasm.js:251

promise http://localhost:8000/xlink_cheerp_wasm.js:331

promise callback* http://localhost:8000/xlink_cheerp_wasm.js:302
Uncaught (in promise) Error: this should be unreachable

__dummy http://localhost:8000/xlink_cheerp_wasm.js:271

__start http://localhost:8000/xlink_cheerp_wasm.js:251

promise http://localhost:8000/xlink_cheerp_wasm.js:331

promise callback* http://localhost:8000/xlink_cheerp_wasm.js:302
I'm not sure exactly which version of cheerp I have. It's a windows installer support gave me that includes file system emulation. The `tstcweb.scr' is a plain text file I have at the root of my cheerp project, though I also tried putting it in an assets subfolder. Note that the open() call is commented out -- it's not making it that far. Is there something that needs to be done to include such files in the package given to the browser?
docs.leaningtech.com
Filesystem emulation
Cheerp is the enterprise-grade C/C++ compiler for the Web and can compile C/C++ into WebAssembly and JavaScript.
18 Replies
apignotti
apignotti11mo ago
The __dummy function is being called, which is a placeholder for some symbol that is not linked. What is the command you are using to build the file? You should also consider using the -cheerp-strict-linking=error or -cheerp-strict-linking=warning to get more verbose information about missing symbols at buildtime.
LetMinnow
LetMinnow11mo ago
I had commented out the -cheerp-strict-linking=warning that I had there before. Restoring that gives me c:\cheerp\bin\clang++ -target cheerp-wasm obj/arg.bc ...<several more files> ... obj/xlink_cheerp_cpp.bc -o xlink_cheerp_wasm.js -cheerp-linear-heap-size=128 -cheerp-pretty-code -cheerp-strict-linking=warning That gives me warning: symbol not defined _ZN6cheerp13FilePreloader8downloadEv Commenting out the code from my first post (void preloadCallback()... files(preloadCallback,...) results in a successful compile/run
apignotti
apignotti11mo ago
Well, the issue seems quite clear
No description
apignotti
apignotti11mo ago
You need to link the libposixcompat library just add -lposixcompat to the command line
LetMinnow
LetMinnow11mo ago
Ok, added -lposixcompat to the command line, now I get this: Uncaught Error: Cheerp: Signal raised __ZN12_GLOBAL__N_111raiseSignalEv http://localhost:8000/xlink_cheerp_wasm.js:159 __ZN6cheerp13FilePreloader14finishDownloadEii ...wasm.js:339 __ZN6cheerp12InvokeHelperIvE6invokeINS_13FilePreloader16DownloadCallbackEJEEEvPT_DpT0_ ...wasm.js:287 cheerpCreateClosure ...wasm.js:352 __ZN6cheerp13FilePreloader8downloadEv ...wasm.js:277 __start ...wasm.js:342 promise ...wasm.js:437 promise callback* ...wasm.js:402 xlink_cheerp_wasm.js:159:8 __ZN12_GLOBAL__N_111raiseSignalEv ...wasm.js:159 abort ...wasm.js line 393 > WebAssembly.instantiate:14566 _ZSt25__throw_bad_function_callB7v160000v_icf ...wasm.js line 393 > WebAssembly.instantiate:10582 _ZN6cheerp13FilePreloader10commitFileERNS0_11PendingFileE ...wasm.js line 393 > WebAssembly.instantiate:22329 __ZN6cheerp13FilePreloader14finishDownloadEii ...wasm.js:339 _ZN6cheerp13FilePreloader16DownloadCallbackclEv ...wasm.js line 393 > WebAssembly.instantiate:23438 __ZN6cheerp12InvokeHelperIvE6invokeINS_13FilePreloader16DownloadCallbackEJEEEvPT_DpT0_ ...wasm.js:287 cheerpCreateClosure ...wasm.js:352 (Async: EventHandlerNonNull) __ZN6cheerp13FilePreloader8downloadEv ...wasm.js:277 _ZN6cheerp13FilePreloaderC2IJPKcEEEOKSt8functionIFvvEEDpT_ ...wasm.js line 393 > WebAssembly.instantiate:34018 __cxx_global_var_init ...wasm.js line 393 > WebAssembly.instantiate:34086 __start ...wasm.js:342 promise ...wasm.js:437 (Async: promise callback) <anonymous> ...wasm.js:402
apignotti
apignotti11mo ago
That looks like an assertion, is there any error message in the console? Please also check the network tab for failures
LetMinnow
LetMinnow11mo ago
no error message in the console. no failures in the network tab -- it found my tstcweb.scr file ok.
apignotti
apignotti11mo ago
Please deploy this compiled example somewhere, if possible directly on a web server so that I can quickly investigate it
LetMinnow
LetMinnow11mo ago
Please see your DMs for the compiled code.
apignotti
apignotti11mo ago
@.letminnow Please try again using a [[cheerp::wasm]] tagged callback, if needed you can call a [[cheerp::genericjs]] function later. I currently believe the compiler is mistakenly letting you use a genericjs function as a callback from wasm context, that is not supported
LetMinnow
LetMinnow11mo ago
I threw that genericjs in trying to get compile error to resolve. Using wasm gives me the below errors (which seems to be the default because I get the same errors without any attribute at all). The example on the page has int fd = open() but then it complains it's not Window *. Then using Window * gives me: xlink_cheerp_cpp.cpp:38:13: error: Cheerp: Type 'Window *' of local variable 'fd' is incompatible with attribute 'wasm' of function 'preloadCallback' Window *fd = open("tstcweb.scr"); ^ xlink_cheerp_cpp.cpp:38:23: error: Cheerp: Attribute 'genericjs' of constructor 'String' is incompatible with attribute 'wasm' of caller function 'preloadCallback' Window *fd = open("tstcweb.scr"); ^ xlink_cheerp_cpp.cpp:38:36: error: Cheerp: Attribute 'genericjs' of function parameter 'url' is incompatible with attribute 'wasm' of caller 'preloadCallback' Window *fd = open("tstcweb.scr"); ^ xlink_cheerp_cpp.cpp:38:36: error: Cheerp: Attribute 'genericjs' of function return 'open' is incompatible with attribute 'wasm' of caller 'preloadCallback'
apignotti
apignotti11mo ago
The errors are expected. The callback itself must be wasm, then you can make another genericjs function to interact with Web APIs Wasm code can call genericjs code, it's just using that as a callback (i.e. an indirect call) that is problematic
LetMinnow
LetMinnow11mo ago
Ok, I made the wasm function into a wrapper that calls a genericjs function and that worked. The open() function results in the file getting downloaded into the browser's downloads folder, which is not what I expected. Where do I find more documentation about the open/read/close? Ultimately, I just need to read the contents of the file for the rest of the code to use. I tried looking for the mentioned libposixcompat library or documentation on it, but I can't find anything.
apignotti
apignotti11mo ago
The open() function results in the file getting downloaded into the browser's downloads
This is not supposed to happen, and it is also extremely unclear to me how that could ever happen. Please send me another build.
open/read/close
They are posix APIs, nothing fancy Also in this case the error is pretty obvious The code is not calling the POSIX open method, which has signature int open(const char *pathname, int flags) It's calling the Web API client::open(const String&) that opens a new browser tab Please note that if you are not comfortable with using POSIX APIs you can use higher level constructs to access the files For example fopen, these all boils down to the same POSIX APIs that the library provides using namespace client; is not necessarily a great solution, since it does import in the global scope a very large number of APIs. Ultimately the using statement is the main reason for this error to happen.
LetMinnow
LetMinnow11mo ago
Is there an include or namespace needed to help the compiler find the posix open()?
apignotti
apignotti11mo ago
No, POSIX APIs are designed for C and hence are in the global namespace. Namespaces did not exists when they were designed. You might try to use the ::open syntax to clarify to the compiler that you are referring to the global namespace.
LetMinnow
LetMinnow11mo ago
First off, a big thank you for all your help in getting this going for me. (Just a quick note for posterity: file reading has to use 'readv()', not 'read()'). Next item: we have extensive debug/trace capability which I have currently adapted to send its output to the js console with 'printf()'. Normally, it just goes to a file descriptor. From the js console we can save to a file if needed -- and doing so will be needed so we can share the sometimes very large output with other and more easily search it, etc. Is there any way cheerp can facilitate saving this output more directly to a file? I understand browsers not allowing write access in general, but they do allow one to download a file to the downloads folder (or elsewhere). If we could get a file descriptor for that, or have a char buffer, or...?
apignotti
apignotti11mo ago
No, there is no support for writing files of any sort in the current implementation we provide It could be implemented, but it would require an ad-hoc project. We have long term plans of significantly upgrade how much normal "syscalls" are supported out-of-the-box, but that will require some time. Even if there is no builtin support at the library level, it does not mean that you could not build a solution at the application level. For example using the standard C library fmemopen or open_memstream + fprintf which should all be supported