I would need some help with using ngspice as a library in a webassembly (wasm) project.
I installed emsdk and newest version of emcc (1.39.20) and downloaded the source of ngspice version 32.
To my greatest surprise, I was able to compile ngspice to wasm target by following this guide:
emconfigure ./configure --with-ngshared --disable-debug
emmake make
(I had to patch configure
a little to pass the checks by adding .out.js a.out.wasm
to this line:)
# The possible output files:
ac_files="a.out a.out.js a.out.wasm conftest.exe conftest a.exe a_out.exe b.out conftest.*"
This produced a libngspice.so.0.0.0
file that I tried to link to from C++ code. However that failed with duplicate symbol: main
. So it seemed that libngspice.so.0.0.0
contained a main
function, that shouldn't have been there if I understand the purpose of the --with-ngshared
of the configure script correctly.
So I manually removed the main
function from main.c
of ngspice and recomplied using the above method. This time I could successfully complie my own project, linking to ngspice. However when I call ngSpice_Init
, I recieve the following runtime errors:
stderr Note: can't find init file.
exception thrown: RuntimeError: unreachable executed,@http://localhost:8001/sim.js line 1802 > WebAssembly.instantiate:wasm-function[67]:0x24e9
@http://localhost:8001/sim.js line 1802 > WebAssembly.instantiate:wasm-function[88]:0x423b
...
Minimal reproducible steps:
- compile ngspice as above
- compile the code below using
em++ -o sim.html sim.cpp lib/libngspice.so
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sharedspice.h"
using namespace std;
int recieve_char(char * str, int id, void* p){
printf("recieved %s\n", str);
}
int recieve_stat(char* status, int id, void* p){
printf("status: %s\n", status);
}
int ngexit(int status, bool unload, bool exit, int id, void* p){
printf("exit: %d\n", status);
}
int recieve_data(vecvaluesall* data, int numstructs, int id, void* p){
printf("data recieved: %f\n", data->vecsa[0]->creal);
}
int recieve_init_data(vecinfoall* data, int id, void* p){
printf("init data recieved from: %d\n", id);
}
int ngrunning(bool running, int id, void* p){
if(running){
printf("ng is running\n");
}else{
printf("ng is not running\n");
}
}
int main(){
ngSpice_Init(&recieve_char, &recieve_stat, &ngexit,
&recieve_data, &recieve_init_data, &ngrunning, (void*)NULL);
char** circarray = (char**)malloc(sizeof(char*) * 7);
circarray[0] = strdup("test array");
circarray[1] = strdup("V1 1 0 1");
circarray[2] = strdup("R1 1 2 1");
circarray[3] = strdup("C1 2 0 1 ic=0");
circarray[4] = strdup(".tran 10u 3 uic");
circarray[5] = strdup(".end");
circarray[6] = NULL;
ngSpice_Circ(circarray);
ngSpice_Command("run");
return 0;
}
So could someone please help me correctly compiling ngspice library to wasm target?
(Before someone asks, yes, I've seen this question, but it didn't help much)