OMNeT++6.0をWebAssemblyで動かす
前にやってたやつでは、forkして普通にcommitしてたけど、OMNeT++のバージョンが上がって、大量の変更が入って動かなくなってしまったので、もう一度作り直してく
zigen/omnetpp-wasm をcloneしてきて、omnetppをomnetpp-6.0.x branchにcheckoutした。
docker_build.shでimageをbuildして、docker_run.shでコンテナに入る。
まずQtのビルドをする。build_all.shを眺めつつビルドしてみる。
cd ~/qtbase
./configure -xplatform wasm-emscripten -prefix $PWD/qtbase -opensource -no-compile-examples -confirm-license
make -j4
make install
よさそう。
次にomnetpp自体のビルドをしていく。前回同様emscripten任せでやってく。
omnetppディレクトリの中で
emconfigure ./configure
するとem++がうまく認識されずにエラーを吐く。とりあえずconfigureいじって通そう
diff --git a/configure b/configure
index 7db1e1c187..d5ee1420a0 100755
--- a/configure
+++ b/configure
@@ -3151,10 +3151,10 @@ $as_echo "no" >&6; }
fi
-if test "$tmp_CXX" = "not found"; then
- OPP_PROBLEM_PACKAGES="$OPP_PROBLEM_PACKAGES g++"
- as_fn_error $? "No C++ compiler found -- one is required to build OMNeT++/OMNEST, and also for model development." "$LINENO" 5
-fi
+#if test "$tmp_CXX" = "not found"; then
+# OPP_PROBLEM_PACKAGES="$OPP_PROBLEM_PACKAGES g++"
+# as_fn_error $? "No C++ compiler found -- one is required to build OMNeT++/OMNEST, and also for model development." "$LINENO" 5
+#fi
#------------------------------------
あとはまぁbuild_all.shを眺めつつOMNeT++のビルドをしていく。
simのビルドでこけてしまった
[root@47b5381e9e79 omnetpp]$ emmake make sim V=1
make: make sim V=1
***** Configuration: MODE=release, TOOLCHAIN_NAME=emcc, SHARED_LIBS=no, LIB_SUFFIX=.a ****
===== Checking environment =====
===== Compiling utils ====
cd /root/omnetpp/src/utils && make
make[1]: Entering directory '/root/omnetpp/src/utils'
echo "#!/bin/sh" >/root/omnetpp/bin/opp_configfilepath && echo '(cd $(dirname $0)/.. && echo $(pwd)/Makefile.inc)' >>/root/omnetpp/bin/opp_configfilepath
cp opp_makemake /root/omnetpp/bin
cp opp_featuretool /root/omnetpp/bin
cp opp_charttool /root/omnetpp/bin
cp opp_test /root/omnetpp/bin
cp opp_fingerprinttest /root/omnetpp/bin
cp opp_shlib_postprocess /root/omnetpp/bin
cp opp_runall /root/omnetpp/bin
cp opp_neddoc /root/omnetpp/bin
cp opp_ide /root/omnetpp/bin
cp omnetpp /root/omnetpp/bin
cp omnest /root/omnetpp/bin
chmod +x /root/omnetpp/bin/opp_makemake /root/omnetpp/bin/opp_test /root/omnetpp/bin/opp_fingerprinttest /root/omnetpp/bin/opp_configfilepath /root/omnetpp/bin/opp_shlib_postprocess /root/omnetpp/bin/opp_runall /root/omnetpp/bin/opp_neddoc /root/omnetpp/bin/opp_ide /root/omnetpp/bin/omnetpp /root/omnetpp/bin/omnest
make[1]: Leaving directory '/root/omnetpp/src/utils'
===== Compiling common ====
cd /root/omnetpp/src/common && make
make[1]: Entering directory '/root/omnetpp/src/common'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/root/omnetpp/src/common'
===== Compiling nedxml ====
cd /root/omnetpp/src/nedxml && make
make[1]: Entering directory '/root/omnetpp/src/nedxml'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/root/omnetpp/src/nedxml'
===== Compiling sim ====
cd /root/omnetpp/src/sim && make
make[1]: Entering directory '/root/omnetpp/src/sim'
/emsdk/upstream/emscripten/em++ -c -Wno-unused-function -O3 -DNDEBUG=1 -ffp-contract=off -MMD -MP -MF /root/omnetpp/out/emcc-release/src/sim/sim_std_m.o.d -fno-omit-frame-pointer -DWITH_QTENV -DWITH_NETBUILDER -I"/root/omnetpp/include" -I"/root/omnetpp/src" -I"/root/omnetpp/include/omnetpp" -o /root/omnetpp/out/emcc-release/src/sim/sim_std_m.o sim_std_m.cc
In file included from sim_std_m.cc:30:
/root/omnetpp/include/omnetpp/sim_std_m.h:16:6: error: Version mismatch! Probably this file was generated by an earlier version of nedtool: 'make clean' should help.
# error Version mismatch! Probably this file was generated by an earlier version of nedtool: 'make clean' should help.
^
sim_std_m.cc:296:17: error: 'getFieldArraySize' marked 'override' but does not override any member functions
virtual int getFieldArraySize(void *object, int field) const override;
^
sim_std_m.cc:298:25: error: 'getFieldDynamicTypeString' marked 'override' but does not override any member functions
virtual const char *getFieldDynamicTypeString(void *object, int field, int i) const override;
^
sim_std_m.cc:299:25: error: 'getFieldValueAsString' marked 'override' but does not override any member functions
virtual std::string getFieldValueAsString(void *object, int field, int i) const override;
^
sim_std_m.cc:300:18: error: 'setFieldValueAsString' marked 'override' but does not override any member functions
virtual bool setFieldValueAsString(void *object, int field, int i, const char *value) const override;
^
sim_std_m.cc:303:19: error: 'getFieldStructValuePointer' marked 'override' but does not override any member functions
virtual void *getFieldStructValuePointer(void *object, int field, int i) const override;
^
sim_std_m.cc:306:26: error: allocating an object of abstract class type 'omnetpp::cObjectDescriptor'
Register_ClassDescriptor(cObjectDescriptor)
^
/root/omnetpp/include/omnetpp/cclassdescriptor.h:233:17: note: unimplemented pure virtual method 'getFieldArraySize' in 'cObjectDescriptor'
virtual int getFieldArraySize(any_ptr object, int field) const = 0;
^
/root/omnetpp/include/omnetpp/cclassdescriptor.h:243:18: note: unimplemented pure virtual method 'setFieldArraySize' in 'cObjectDescriptor'
virtual void setFieldArraySize(any_ptr object, int field, int size) const = 0;
^
/root/omnetpp/include/omnetpp/cclassdescriptor.h:266:25: note: unimplemented pure virtual method 'getFieldValueAsString' in 'cObjectDescriptor'
virtual std::string getFieldValueAsString(any_ptr object, int field, int i) const = 0;
^
/root/omnetpp/include/omnetpp/cclassdescriptor.h:276:18: note: unimplemented pure virtual method 'setFieldValueAsString' in 'cObjectDescriptor'
virtual void setFieldValueAsString(any_ptr object, int field, int i, const char *value) const = 0;
^
/root/omnetpp/include/omnetpp/cclassdescriptor.h:285:20: note: unimplemented pure virtual method 'getFieldValue' in 'cObjectDescriptor'
virtual cValue getFieldValue(any_ptr object, int field, int i) const = 0;
^
/root/omnetpp/include/omnetpp/cclassdescriptor.h:295:18: note: unimplemented pure virtual method 'setFieldValue' in 'cObjectDescriptor'
virtual void setFieldValue(any_ptr object, int field, int i, const cValue& value) const = 0;
^
/root/omnetpp/include/omnetpp/cclassdescriptor.h:310:21: note: unimplemented pure virtual method 'getFieldStructValuePointer' in 'cObjectDescriptor'
virtual any_ptr getFieldStructValuePointer(any_ptr object, int field, int i) const = 0;
^
/root/omnetpp/include/omnetpp/cclassdescriptor.h:320:18: note: unimplemented pure virtual method 'setFieldStructValuePointer' in 'cObjectDescriptor'
virtual void setFieldStructValuePointer(any_ptr object, int field, int i, any_ptr ptr) const = 0;
^
sim_std_m.cc:494:48: error: no viable conversion from 'void *' to 'omnetpp::any_ptr'
return basedesc->getFieldArraySize(object, field);
^~~~~~
/root/omnetpp/include/omnetpp/any_ptr.h:81:5: note: candidate constructor not viable: cannot convert argument of incomplete type 'void *' to 'const omnetpp::any_ptr &' for 1st argument
any_ptr(const any_ptr &other) : ptr(other.ptr), type(other.type) {}
^
/root/omnetpp/include/omnetpp/any_ptr.h:71:14: note: explicit constructor is not a candidate
explicit any_ptr(std::nullptr_t) : ptr(nullptr), type(&typeid(std::nullptr_t)) {}
^
/root/omnetpp/include/omnetpp/any_ptr.h:74:14: note: explicit constructor is not a candidate
explicit any_ptr(T *ptr) : ptr(ptr), type(&typeid(T*)) {}
^
/root/omnetpp/include/omnetpp/any_ptr.h:77:14: note: explicit constructor is not a candidate
explicit any_ptr(const T *ptr) : any_ptr(const_cast<T*>(ptr)) {}
^
/root/omnetpp/include/omnetpp/cclassdescriptor.h:233:43: note: passing argument to parameter 'object' here
virtual int getFieldArraySize(any_ptr object, int field) const = 0;
^
sim_std_m.cc:508:56: error: no viable conversion from 'void *' to 'omnetpp::any_ptr'
return basedesc->getFieldDynamicTypeString(object,field,i);
^~~~~~
/root/omnetpp/include/omnetpp/any_ptr.h:81:5: note: candidate constructor not viable: cannot convert argument of incomplete type 'void *' to 'const omnetpp::any_ptr &' for 1st argument
any_ptr(const any_ptr &other) : ptr(other.ptr), type(other.type) {}
^
/root/omnetpp/include/omnetpp/any_ptr.h:71:14: note: explicit constructor is not a candidate
explicit any_ptr(std::nullptr_t) : ptr(nullptr), type(&typeid(std::nullptr_t)) {}
^
/root/omnetpp/include/omnetpp/any_ptr.h:74:14: note: explicit constructor is not a candidate
explicit any_ptr(T *ptr) : ptr(ptr), type(&typeid(T*)) {}
^
/root/omnetpp/include/omnetpp/any_ptr.h:77:14: note: explicit constructor is not a candidate
explicit any_ptr(const T *ptr) : any_ptr(const_cast<T*>(ptr)) {}
^
/root/omnetpp/include/omnetpp/cclassdescriptor.h:256:59: note: passing argument to parameter 'object' here
virtual const char *getFieldDynamicTypeString(any_ptr object, int field, int i) const {return nullptr;}
^
sim_std_m.cc:522:52: error: no viable conversion from 'void *' to 'omnetpp::any_ptr'
return basedesc->getFieldValueAsString(object,field,i);
^~~~~~
/root/omnetpp/include/omnetpp/any_ptr.h:81:5: note: candidate constructor not viable: cannot convert argument of incomplete type 'void *' to 'const omnetpp::any_ptr &' for 1st argument
any_ptr(const any_ptr &other) : ptr(other.ptr), type(other.type) {}
^
/root/omnetpp/include/omnetpp/any_ptr.h:71:14: note: explicit constructor is not a candidate
explicit any_ptr(std::nullptr_t) : ptr(nullptr), type(&typeid(std::nullptr_t)) {}
^
/root/omnetpp/include/omnetpp/any_ptr.h:74:14: note: explicit constructor is not a candidate
explicit any_ptr(T *ptr) : ptr(ptr), type(&typeid(T*)) {}
^
/root/omnetpp/include/omnetpp/any_ptr.h:77:14: note: explicit constructor is not a candidate
explicit any_ptr(const T *ptr) : any_ptr(const_cast<T*>(ptr)) {}
^
/root/omnetpp/include/omnetpp/cclassdescriptor.h:266:55: note: passing argument to parameter 'object' here
virtual std::string getFieldValueAsString(any_ptr object, int field, int i) const = 0;
^
sim_std_m.cc:541:52: error: no viable conversion from 'void *' to 'omnetpp::any_ptr'
return basedesc->setFieldValueAsString(object,field,i,value);
^~~~~~
/root/omnetpp/include/omnetpp/any_ptr.h:81:5: note: candidate constructor not viable: cannot convert argument of incomplete type 'void *' to 'const omnetpp::any_ptr &' for 1st argument
any_ptr(const any_ptr &other) : ptr(other.ptr), type(other.type) {}
^
/root/omnetpp/include/omnetpp/any_ptr.h:71:14: note: explicit constructor is not a candidate
explicit any_ptr(std::nullptr_t) : ptr(nullptr), type(&typeid(std::nullptr_t)) {}
^
/root/omnetpp/include/omnetpp/any_ptr.h:74:14: note: explicit constructor is not a candidate
explicit any_ptr(T *ptr) : ptr(ptr), type(&typeid(T*)) {}
^
/root/omnetpp/include/omnetpp/any_ptr.h:77:14: note: explicit constructor is not a candidate
explicit any_ptr(const T *ptr) : any_ptr(const_cast<T*>(ptr)) {}
^
/root/omnetpp/include/omnetpp/cclassdescriptor.h:276:48: note: passing argument to parameter 'object' here
virtual void setFieldValueAsString(any_ptr object, int field, int i, const char *value) const = 0;
^
sim_std_m.cc:541:20: error: cannot initialize return object of type 'bool' with an rvalue of type 'void'
return basedesc->setFieldValueAsString(object,field,i,value);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sim_std_m.cc:569:57: error: no viable conversion from 'void *' to 'omnetpp::any_ptr'
return basedesc->getFieldStructValuePointer(object, field, i);
^~~~~~
/root/omnetpp/include/omnetpp/any_ptr.h:81:5: note: candidate constructor not viable: cannot convert argument of incomplete type 'void *' to 'const omnetpp::any_ptr &' for 1st argument
any_ptr(const any_ptr &other) : ptr(other.ptr), type(other.type) {}
^
/root/omnetpp/include/omnetpp/any_ptr.h:71:14: note: explicit constructor is not a candidate
explicit any_ptr(std::nullptr_t) : ptr(nullptr), type(&typeid(std::nullptr_t)) {}
^
/root/omnetpp/include/omnetpp/any_ptr.h:74:14: note: explicit constructor is not a candidate
explicit any_ptr(T *ptr) : ptr(ptr), type(&typeid(T*)) {}
^
/root/omnetpp/include/omnetpp/any_ptr.h:77:14: note: explicit constructor is not a candidate
explicit any_ptr(const T *ptr) : any_ptr(const_cast<T*>(ptr)) {}
^
/root/omnetpp/include/omnetpp/cclassdescriptor.h:310:56: note: passing argument to parameter 'object' here
virtual any_ptr getFieldStructValuePointer(any_ptr object, int field, int i) const = 0;
^
sim_std_m.cc:569:20: error: no viable conversion from returned value of type 'omnetpp::any_ptr' to function return type 'void *'
return basedesc->getFieldStructValuePointer(object, field, i);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sim_std_m.cc:598:17: error: 'getFieldArraySize' marked 'override' but does not override any member functions
virtual int getFieldArraySize(void *object, int field) const override;
^
sim_std_m.cc:600:25: error: 'getFieldDynamicTypeString' marked 'override' but does not override any member functions
virtual const char *getFieldDynamicTypeString(void *object, int field, int i) const override;
^
sim_std_m.cc:601:25: error: 'getFieldValueAsString' marked 'override' but does not override any member functions
virtual std::string getFieldValueAsString(void *object, int field, int i) const override;
^
sim_std_m.cc:602:18: error: 'setFieldValueAsString' marked 'override' but does not override any member functions
virtual bool setFieldValueAsString(void *object, int field, int i, const char *value) const override;
^
sim_std_m.cc:605:19: error: 'getFieldStructValuePointer' marked 'override' but does not override any member functions
virtual void *getFieldStructValuePointer(void *object, int field, int i) const override;
^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.
em++: error: '/emsdk/upstream/bin/clang++ -target wasm32-unknown-emscripten -DEMSCRIPTEN -fignore-exceptions -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr -D__EMSCRIPTEN_major__=2 -D__EMSCRIPTEN_minor__=0 -D__EMSCRIPTEN_tiny__=25 -D_LIBCPP_ABI_VERSION=2 -Dunix -D__unix -D__unix__ -Werror=implicit-function-declaration -Xclang -iwithsysroot/include/SDL --sysroot=/emsdk/upstream/emscripten/cache/sysroot -Xclang -iwithsysroot/include/compat -c -Wno-unused-function -O3 -DNDEBUG=1 -ffp-contract=off -MMD -MP -MF /root/omnetpp/out/emcc-release/src/sim/sim_std_m.o.d -fno-omit-frame-pointer -DWITH_QTENV -DWITH_NETBUILDER -I/root/omnetpp/include -I/root/omnetpp/src -I/root/omnetpp/include/omnetpp sim_std_m.cc -o /root/omnetpp/out/emcc-release/src/sim/sim_std_m.o' failed (returned 1)
make[1]: *** [Makefile:111: /root/omnetpp/out/emcc-release/src/sim/sim_std_m.o] Error 1
make[1]: Leaving directory '/root/omnetpp/src/sim'
make: *** [Makefile:134: sim] Error 2
emmake: error: 'make sim V=1' failed (returned 2)
このエラー、docker imageに突っ込んでおいたopp_msgtoolsのバージョンが古いのが原因か。更新しよう
直した。
とりあえずビルドはできて、samplesのtictocもビルドできるようになった。
しかし、htmlなどが生成されないので、前回と同じようにMakefile.inc.inをいじって、make時に生成していく。
Makefile.inc.inのpatchをつくる。とりあえず前回のから引っ張ってくるとこんな感じ
diff --git a/Makefile.inc.in b/Makefile.inc.in
index fe9fcd8210..3929751092 100644
--- a/Makefile.inc.in
+++ b/Makefile.inc.in
@@ -187,7 +187,7 @@ IMPLIB_SUFFIX = @IMPLIB_SUFFIX@
IMPDEF_SUFFIX = @IMPDEF_SUFFIX@
SHARED_LIB_SUFFIX = @SHARED_LIB_SUFFIX@
JNI_LIB_SUFFIX = @JNI_LIB_SUFFIX@
-EXE_SUFFIX = @EXE_SUFFIX@
+EXE_SUFFIX = .html
LIB_PREFIX = @LIB_PREFIX@
#
@@ -199,6 +199,51 @@ ALL_ENV_LIBS = $(CMDENV_LIBS)
KERNEL_LIBS = -loppsim$D
OPPMAIN_LIB = $(LDFLAG_LIB)oppmain$D
+#
+# for web assembly
+#
+ifneq ($(EMSCRIPTEN),)
+ SHARED_LIBS=no
+ BUILDING_UILIBS=no
+ WITH_TKENV=no
+ WITH_OSG=no
+ WITH_OSGEARTH=no
+ WITH_PARSIM=no
+ ARFLAG_OUT= qcs
+ WHOLE_ARCHIVE_ON = -Wl,--whole-archive
+ WHOLE_ARCHIVE_OFF =
+ EXE_SUFFIX = .js
+ CFLAGS_DEBUG+= -gsource-map -g3 -O0 --source-map-base http://localhost:8080/
+ CFLAGS_RELEASE+= -O3 -Os
+ PRELOAD_FILES ?= --preload-file .
+ CFLAGS+= -s DISABLE_EXCEPTION_CATCHING=0 -s USE_PTHREADS=0
+ LDFLAGS+= --bind -s ASYNCIFY=1 -s USE_PTHREADS=0 -s PTHREAD_POOL_SIZE=1 -s TOTAL_MEMORY=1GB -s WASM=1 -s FULL_ES2=1 -s USE_WEBGL2=1 -s NO_EXIT_RUNTIME=0 -s EXPORTED_RUNTIME_METHODS=["UTF16ToString","stringToUTF16","ccall","cwrap"] $(PRELOAD_FILES) --preload-file /root/omnetpp/images@images --preload-file /root/wasm-qtenvrc@.qtenvrc -s DISABLE_EXCEPTION_CATCHING=0
+ ifeq ($(MODE),debug)
+ LDFLAGS += -O3 -Os -s ASSERTIONS=2 -s SAFE_HEAP=1 -s EXCEPTION_DEBUG=0
+ #LDFLAGS += -gsource-map -g3 -O0 --source-map-base http://localhost:8080/ -s ASSERTIONS=2 -s SAFE_HEAP=1 -s EXCEPTION_DEBUG=0
+ else
+ LDFLAGS += -O3 -Os
+ endif
+ ifneq (,$(wildcard $(CURDIR)/post.js))
+ LDFLAGS += --post-js ./post.js
+ endif
+
+default: all
+
+index.html: $O/$(TARGET)
+ echo $O/$(TARGET)
+ cp /root/qtbase/qtbase/plugins/platforms/wasm_shell.html $O/index.html
+ cp /root/qtbase/qtbase/plugins/platforms/qtloader.js $O/qtloader.js
+ cp /root/qtbase/qtbase/plugins/platforms/qtlogo.svg $O/qtlogo.svg
+ cp /root/node_exec_template.js $O/$(TARGET:.js=)
+ sed -i 's/@APPNAME@/$(basename $(TARGET))/' $O/index.html
+ sed -i 's/@APPNAME@/$(basename $(TARGET))/' $O/qtloader.js
+ sed -i 's/@APPNAME@/$(basename $(TARGET))/' $O/$(TARGET:.js=)
+
+%.js: index.html
+
+endif
+
#
# flags and libraries required for Qtenv
#
そして新たなエラーが。。。
[root@f72e2f39687e omnetpp]$ emmake make V=1 common
make: make V=1 common
***** Configuration: MODE=release, TOOLCHAIN_NAME=emcc, SHARED_LIBS=no, LIB_SUFFIX=.a ****
===== Checking environment =====
===== Compiling utils ====
cd /root/omnetpp/src/utils && make
make[1]: Entering directory '/root/omnetpp/src/utils'
echo "#!/bin/sh" >/root/omnetpp/bin/opp_configfilepath && echo '(cd $(dirname $0)/.. && echo $(pwd)/Makefile.inc)' >>/root/omnetpp/bin/opp_configfilepath
cp opp_makemake /root/omnetpp/bin
cp opp_featuretool /root/omnetpp/bin
cp opp_charttool /root/omnetpp/bin
cp opp_test /root/omnetpp/bin
cp opp_fingerprinttest /root/omnetpp/bin
cp opp_shlib_postprocess /root/omnetpp/bin
cp opp_runall /root/omnetpp/bin
cp opp_neddoc /root/omnetpp/bin
cp opp_ide /root/omnetpp/bin
cp omnetpp /root/omnetpp/bin
cp omnest /root/omnetpp/bin
chmod +x /root/omnetpp/bin/opp_makemake /root/omnetpp/bin/opp_test /root/omnetpp/bin/opp_fingerprinttest /root/omnetpp/bin/opp_configfilepath /root/omnetpp/bin/opp_shlib_postprocess /root/omnetpp/bin/opp_runall /root/omnetpp/bin/opp_neddoc /root/omnetpp/bin/opp_ide /root/omnetpp/bin/omnetpp /root/omnetpp/bin/omnest
make[1]: Leaving directory '/root/omnetpp/src/utils'
===== Compiling common ====
cd /root/omnetpp/src/common && make
make[1]: Entering directory '/root/omnetpp/src/common'
Creating static library: /root/omnetpp/out/emcc-release/src/common/liboppcommon.a
/emsdk/upstream/emscripten/emar cr qcs /root/omnetpp/out/emcc-release/src/common/liboppcommon.a /root/omnetpp/out/emcc-release/src/common/lcgrandom.o /root/omnetpp/out/emcc-release/src/common/filelock.o /root/omnetpp/out/emcc-release/src/common/filereader.o /root/omnetpp/out/emcc-release/src/common/linetokenizer.o /root/omnetpp/out/emcc-release/src/common/stringpool.o /root/omnetpp/out/emcc-release/src/common/pooledstring.o /root/omnetpp/out/emcc-release/src/common/stringtokenizer.o /root/omnetpp/out/emcc-release/src/common/fnamelisttokenizer.o /root/omnetpp/out/emcc-release/src/common/expression.o /root/omnetpp/out/emcc-release/src/common/lex.expressionyy.o /root/omnetpp/out/emcc-release/src/common/expression.tab.o /root/omnetpp/out/emcc-release/src/common/matchexpression.o /root/omnetpp/out/emcc-release/src/common/matchexpressionlexer.o /root/omnetpp/out/emcc-release/src/common/matchexpression.tab.o /root/omnetpp/out/emcc-release/src/common/patternmatcher.o /root/omnetpp/out/emcc-release/src/common/unitconversion.o /root/omnetpp/out/emcc-release/src/common/displaystring.o /root/omnetpp/out/emcc-release/src/common/fileglobber.o /root/omnetpp/out/emcc-release/src/common/fileutil.o /root/omnetpp/out/emcc-release/src/common/stringutil.o /root/omnetpp/out/emcc-release/src/common/commonutil.o /root/omnetpp/out/emcc-release/src/common/exception.o /root/omnetpp/out/emcc-release/src/common/bigdecimal.o /root/omnetpp/out/emcc-release/src/common/enumstr.o /root/omnetpp/out/emcc-release/src/common/colorutil.o /root/omnetpp/out/emcc-release/src/common/statistics.o /root/omnetpp/out/emcc-release/src/common/sqlite3.o /root/omnetpp/out/emcc-release/src/common/formattedprinter.o /root/omnetpp/out/emcc-release/src/common/csvwriter.o /root/omnetpp/out/emcc-release/src/common/jsonwriter.o /root/omnetpp/out/emcc-release/src/common/sqliteresultfileschema.o /root/omnetpp/out/emcc-release/src/common/sqlitescalarfilewriter.o /root/omnetpp/out/emcc-release/src/common/sqlitevectorfilewriter.o /root/omnetpp/out/emcc-release/src/common/omnetppscalarfilewriter.o /root/omnetpp/out/emcc-release/src/common/omnetppvectorfilewriter.o /root/omnetpp/out/emcc-release/src/common/exprnode.o /root/omnetpp/out/emcc-release/src/common/exprnodes.o /root/omnetpp/out/emcc-release/src/common/exprvalue.o /root/omnetpp/out/emcc-release/src/common/intutil.o /root/omnetpp/out/emcc-release/src/common/any_ptr.o /root/omnetpp/out/emcc-release/src/common/saxparser_default.o /root/omnetpp/out/emcc-release/src/common/saxparser_libxml.o /root/omnetpp/out/emcc-release/src/common/saxparser_yxml.o /root/omnetpp/out/emcc-release/src/common/yxml.o
/emsdk/upstream/bin/llvm-ar: error: /root/omnetpp/out/emcc-release/src/common/liboppcommon.a: No such file or directory
make[1]: *** [Makefile:107: /root/omnetpp/out/emcc-release/src/common/liboppcommon.a] Error 1
make[1]: Leaving directory '/root/omnetpp/src/common'
make: *** [Makefile:134: common] Error 2
emmake: error: 'make V=1 common' failed (returned 2)
/emsdk/upstream/emscripten/emar cr qcs
emarにcrとqcsが渡ってるのがおかしい。qcsだけでいいはずだ。
というわけで、crを取り除いてemarを叩いたらビルドが通った。
次は、これがどこで埋め込まれたかを探して、直していく
sampleをmakeしてみたらduplicate symbolでこけた。シンボルがどのタイミングで突っ込まれたのかを知る必要がある
em++: warning: ignoring unsupported linker flag: `-rpath` [-Wlinkflags]
em++: warning: ignoring unsupported linker flag: `-rpath` [-Wlinkflags]
em++: warning: ignoring unsupported linker flag: `-rpath` [-Wlinkflags]
em++: warning: ignoring unsupported linker flag: `-rpath=/root/qtbase/qtbase/lib` [-Wlinkflags]
wasm-ld: error: duplicate symbol: omnetpp::envir::omnetapps
>>> defined in /root/omnetpp/lib/liboppenvir.a(appreg.o)
>>> defined in /root/omnetpp/lib/liboppenvir.a(appreg.o)
wasm-ld: error: duplicate symbol: omnetpp::envir::cOmnetAppRegistration::chooseBest()
>>> defined in /root/omnetpp/lib/liboppenvir.a(appreg.o)
>>> defined in /root/omnetpp/lib/liboppenvir.a(appreg.o)
wasm-ld: error: duplicate symbol: omnetpp::envir::ArgList::parse(int, char**, char const*)
>>> defined in /root/omnetpp/lib/liboppenvir.a(args.o)
>>> defined in /root/omnetpp/lib/liboppenvir.a(args.o)
wasm-ld: error: duplicate symbol: omnetpp::envir::ArgList::isValidOption(char) const
>>> defined in /root/omnetpp/lib/liboppenvir.a(args.o)
>>> defined in /root/omnetpp/lib/liboppenvir.a(args.o)
wasm-ld: error: duplicate symbol: omnetpp::envir::ArgList::hasArg(char) const
>>> defined in /root/omnetpp/lib/liboppenvir.a(args.o)
>>> defined in /root/omnetpp/lib/liboppenvir.a(args.o)
wasm-ld: error: duplicate symbol: omnetpp::envir::ArgList::hasOptionalArg(char) const
>>> defined in /root/omnetpp/lib/liboppenvir.a(args.o)
>>> defined in /root/omnetpp/lib/liboppenvir.a(args.o)
wasm-ld: error: duplicate symbol: omnetpp::envir::ArgList::getLongOptions() const
>>> defined in /root/omnetpp/lib/liboppenvir.a(args.o)
>>> defined in /root/omnetpp/lib/liboppenvir.a(args.o)
wasm-ld: error: duplicate symbol: omnetpp::envir::ArgList::optionGiven(char) const
>>> defined in /root/omnetpp/lib/liboppenvir.a(args.o)
>>> defined in /root/omnetpp/lib/liboppenvir.a(args.o)
wasm-ld: error: duplicate symbol: omnetpp::envir::ArgList::longOptionGiven(char const*) const
>>> defined in /root/omnetpp/lib/liboppenvir.a(args.o)
>>> defined in /root/omnetpp/lib/liboppenvir.a(args.o)
wasm-ld: error: duplicate symbol: omnetpp::envir::ArgList::optionValue(char, int) const
>>> defined in /root/omnetpp/lib/liboppenvir.a(args.o)
>>> defined in /root/omnetpp/lib/liboppenvir.a(args.o)
wasm-ld: error: duplicate symbol: omnetpp::envir::ArgList::optionValues(char) const
>>> defined in /root/omnetpp/lib/liboppenvir.a(args.o)
>>> defined in /root/omnetpp/lib/liboppenvir.a(args.o)
wasm-ld: error: duplicate symbol: omnetpp::envir::ArgList::argument(int) const
>>> defined in /root/omnetpp/lib/liboppenvir.a(args.o)
>>> defined in /root/omnetpp/lib/liboppenvir.a(args.o)
wasm-ld: error: duplicate symbol: omnetpp::envir::CFGID_LOAD_LIBS
>>> defined in /root/omnetpp/lib/liboppenvir.a(startup.o)
>>> defined in /root/omnetpp/lib/liboppenvir.a(startup.o)
wasm-ld: error: duplicate symbol: omnetpp::envir::CFGID_CONFIGURATION_CLASS
>>> defined in /root/omnetpp/lib/liboppenvir.a(startup.o)
>>> defined in /root/omnetpp/lib/liboppenvir.a(startup.o)
arのオプションを直した。5の時と変わってるのか?
とりあえずomnetpp/samples/tictocで emmake make index.html
するとjs, html, data, wasmが一通り生成される。
omnetpp/samples/tictoc/emcc-releaseでpython3 -m http.server
してlocalhost:8000にアクセスすると、wasmが動く。
が、エラーを吐いて死ぬ。
OMNeT++ Discrete Event Simulation (C) 1992-2022 Andras Varga, OpenSim Ltd.
qtloader.js:372 Version: 6.0, build: internal, edition: Academic Public License -- NOT FOR COMMERCIAL USE
qtloader.js:372 See the license for distribution terms and warranty disclaimer
qtloader.js:372
qtloader.js:372 Setting up Qtenv...
qtloader.js:372
qtloader.js:372 Loading NED files from .: 19
qtloader.js:372
qtloader.js:372 Loading images from 'images': *: 0 abstract/*: 90 background/*: 4 block/*: 325 device/*: 195 logo/*: 3 maps/*: 9 misc/*: 70 msg/*: 55 old/*: 111 Warning: Could not load image '/images/old/app.gif'
qtloader.js:372 Warning: Could not load image '/images/old/ball.gif'
qtloader.js:372 Warning: Could not load image '/images/old/ball2.gif'
qtloader.js:372 Warning: Could not load image '/images/old/ball2_s.gif'
qtloader.js:372 Warning: Could not load image '/images/old/ball2_vs.gif'
qtloader.js:372 Warning: Could not load image '/images/old/ball_s.gif'
qtloader.js:372 Warning: Could not load image '/images/old/ball_vs.gif'
qtloader.js:372 Warning: Could not load image '/images/old/bluebox.gif'
qtloader.js:372 Warning: Could not load image '/images/old/box1.gif'
qtloader.js:372 Warning: Could not load image '/images/old/box1_s.gif'
qtloader.js:372 Warning: Could not load image '/images/old/box2.gif'
qtloader.js:372 Warning: Could not load image '/images/old/box2_s.gif'
qtloader.js:372 Warning: Could not load image '/images/old/box3.gif'
qtloader.js:372 Warning: Could not load image '/images/old/box3_s.gif'
qtloader.js:372 Warning: Could not load image '/images/old/browser.gif'
qtloader.js:372 Warning: Could not load image '/images/old/bwcomp.gif'
qtloader.js:372 Warning: Could not load image '/images/old/bwcomp_s.gif'
qtloader.js:372 Warning: Could not load image '/images/old/bwgen.gif'
qtloader.js:372 Warning: Could not load image '/images/old/bwgen_s.gif'
qtloader.js:372 Warning: Could not load image '/images/old/bwsink.gif'
qtloader.js:372 Warning: Could not load image '/images/old/bwsink_s.gif'
qtloader.js:372 Warning: Could not load image '/images/old/bwxcon_s.gif'
qtloader.js:372 Warning: Could not load image '/images/old/bwxconn.gif'
qtloader.js:372 Warning: Could not load image '/images/old/card1.gif'
qtloader.js:372 Warning: Could not load image '/images/old/card2.gif'
qtloader.js:372 Warning: Could not load image '/images/old/cloud.gif'
qtloader.js:372 Warning: Could not load image '/images/old/cloud_l.gif'
qtloader.js:372 Warning: Could not load image '/images/old/cloud_s.gif'
qtloader.js:372 Warning: Could not load image '/images/old/cogwheel.gif'
qtloader.js:372 Warning: Could not load image '/images/old/cogwheel2.gif'
qtloader.js:372 Warning: Could not load image '/images/old/cogwheel2_s.gif'
qtloader.js:372 Warning: Could not load image '/images/old/comp.gif'
qtloader.js:372 Warning: Could not load image '/images/old/comp2.gif'
qtloader.js:372 Warning: Could not load image '/images/old/comp2_s.gif'
qtloader.js:372 Warning: Could not load image '/images/old/comp_a.gif'
qtloader.js:372 Warning: Could not load image '/images/old/comp_a_s.gif'
qtloader.js:372 Warning: Could not load image '/images/old/comp_s.gif'
qtloader.js:372 Warning: Could not load image '/images/old/delay.gif'
qtloader.js:372 Warning: Could not load image '/images/old/dialphone.gif'
qtloader.js:372 Warning: Could not load image '/images/old/drive1.gif'
qtloader.js:372 Warning: Could not load image '/images/old/drive2.gif'
qtloader.js:372 Warning: Could not load image '/images/old/earth1.gif'
qtloader.js:372 Warning: Could not load image '/images/old/floppy1.gif'
qtloader.js:372 Warning: Could not load image '/images/old/floppy2.gif'
qtloader.js:372 Warning: Could not load image '/images/old/folder.gif'
qtloader.js:372 Warning: Could not load image '/images/old/fork.gif'
qtloader.js:372 Warning: Could not load image '/images/old/gen.gif'
qtloader.js:372 Warning: Could not load image '/images/old/greenbox.gif'
qtloader.js:372 Warning: Could not load image '/images/old/handset1.gif'
qtloader.js:372 Warning: Could not load image '/images/old/handset1_s.gif'
qtloader.js:372 Warning: Could not load image '/images/old/handset2_s.gif'
qtloader.js:372 Warning: Could not load image '/images/old/harddisk.gif'
qtloader.js:372 Warning: Could not load image '/images/old/hook.gif'
qtloader.js:372 Warning: Could not load image '/images/old/iface.gif'
qtloader.js:372 Warning: Could not load image '/images/old/ipc.gif'
qtloader.js:372 Warning: Could not load image '/images/old/laptop.gif'
qtloader.js:372 Warning: Could not load image '/images/old/laptop2.gif'
qtloader.js:372 Warning: Could not load image '/images/old/laptop2_l.gif'
qtloader.js:372 Warning: Could not load image '/images/old/laptop3.gif'
qtloader.js:372 Warning: Could not load image '/images/old/mailbox.gif'
qtloader.js:372 Warning: Could not load image '/images/old/monitor.gif'
qtloader.js:372 Warning: Could not load image '/images/old/pc.gif'
qtloader.js:372 Warning: Could not load image '/images/old/pc_s.gif'
qtloader.js:372 Warning: Could not load image '/images/old/pccard.gif'
qtloader.js:372 Warning: Could not load image '/images/old/pccard_s.gif'
qtloader.js:372 Warning: Could not load image '/images/old/pctower1.gif'
qtloader.js:372 Warning: Could not load image '/images/old/pctower2.gif'
qtloader.js:372 Warning: Could not load image '/images/old/pda1.gif'
qtloader.js:372 Warning: Could not load image '/images/old/pda2.gif'
qtloader.js:372 Warning: Could not load image '/images/old/pda3.gif'
qtloader.js:372 Warning: Could not load image '/images/old/penguin.gif'
qtloader.js:372 Warning: Could not load image '/images/old/printer.gif'
qtloader.js:372 Warning: Could not load image '/images/old/proc1.gif'
qtloader.js:372 Warning: Could not load image '/images/old/proc2.gif'
qtloader.js:372 Warning: Could not load image '/images/old/prot1.gif'
qtloader.js:372 Warning: Could not load image '/images/old/prot2.gif'
qtloader.js:372 Warning: Could not load image '/images/old/prot3.gif'
qtloader.js:372 Warning: Could not load image '/images/old/queue.gif'
qtloader.js:372 Warning: Could not load image '/images/old/redbox.gif'
qtloader.js:372 Warning: Could not load image '/images/old/ring.gif'
qtloader.js:372 Warning: Could not load image '/images/old/router.gif'
qtloader.js:372 Warning: Could not load image '/images/old/router2.gif'
qtloader.js:372 Warning: Could not load image '/images/old/router2_s.gif'
qtloader.js:372 Warning: Could not load image '/images/old/router3.gif'
qtloader.js:372 Warning: Could not load image '/images/old/router_s.gif'
qtloader.js:372 Warning: Could not load image '/images/old/server1.gif'
qtloader.js:372 Warning: Could not load image '/images/old/server1_l.gif'
qtloader.js:372 Warning: Could not load image '/images/old/sink.gif'
qtloader.js:372 Warning: Could not load image '/images/old/srouter.gif'
qtloader.js:372 Warning: Could not load image '/images/old/switch1.gif'
qtloader.js:372 Warning: Could not load image '/images/old/switch1_s.gif'
qtloader.js:372 Warning: Could not load image '/images/old/switch2.gif'
qtloader.js:372 Warning: Could not load image '/images/old/telnet.gif'
qtloader.js:372 Warning: Could not load image '/images/old/x_active.gif'
qtloader.js:372 Warning: Could not load image '/images/old/x_asleep.gif'
qtloader.js:372 Warning: Could not load image '/images/old/x_blank.gif'
qtloader.js:372 Warning: Could not load image '/images/old/x_busy.gif'
qtloader.js:372 Warning: Could not load image '/images/old/x_check.gif'
qtloader.js:372 Warning: Could not load image '/images/old/x_cross.gif'
qtloader.js:372 Warning: Could not load image '/images/old/x_down.gif'
qtloader.js:372 Warning: Could not load image '/images/old/x_excl.gif'
qtloader.js:372 Warning: Could not load image '/images/old/x_green.gif'
qtloader.js:372 Warning: Could not load image '/images/old/x_hglass.gif'
qtloader.js:372 Warning: Could not load image '/images/old/x_noentry.gif'
qtloader.js:372 Warning: Could not load image '/images/old/x_off.gif'
qtloader.js:372 Warning: Could not load image '/images/old/x_question.gif'
qtloader.js:372 Warning: Could not load image '/images/old/x_red.gif'
qtloader.js:372 Warning: Could not load image '/images/old/x_smoke.gif'
qtloader.js:372 Warning: Could not load image '/images/old/x_up.gif'
qtloader.js:372 Warning: Could not load image '/images/old/x_yellow.gif'
qtloader.js:372 Warning: Could not load image '/images/old/xconn.gif'
qtloader.js:372 src/*: 0 src/abstract/*: 0 src/block/*: 0 src/device/*: 0 src/logo/*: 0 src/misc/*: 0 src/msg/*: 0 src/status/*: 0 src/unused/*: 0 status/*: 28 Warning: Could not load image '/images/status/active.gif'
qtloader.js:372 Warning: Could not load image '/images/status/asleep.gif'
qtloader.js:372 Warning: Could not load image '/images/status/busy.gif'
qtloader.js:372 Warning: Could not load image '/images/status/check.gif'
qtloader.js:372 Warning: Could not load image '/images/status/cross.gif'
qtloader.js:372 Warning: Could not load image '/images/status/down.gif'
qtloader.js:372 Warning: Could not load image '/images/status/excl.gif'
qtloader.js:372 Warning: Could not load image '/images/status/green.gif'
qtloader.js:372 Warning: Could not load image '/images/status/hourglass.gif'
qtloader.js:372 Warning: Could not load image '/images/status/lightning.gif'
qtloader.js:372 Warning: Could not load image '/images/status/noentry.gif'
qtloader.js:372 Warning: Could not load image '/images/status/off.gif'
qtloader.js:372 Warning: Could not load image '/images/status/question.gif'
qtloader.js:372 Warning: Could not load image '/images/status/red.gif'
qtloader.js:372 Warning: Could not load image '/images/status/smoke.gif'
qtloader.js:372 Warning: Could not load image '/images/status/up.gif'
qtloader.js:372 Warning: Could not load image '/images/status/yellow.gif'
qtloader.js:372
qtloader.js:372 Loading images from '/root/omnetpp/images': *: 0
qtloader.js:372
qtloader.js:382 qt.qpa.plugin: Could not find the Qt platform plugin "wasm" in ""
qtloader.js:382 This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.
qtloader.js:382
qtloader.js:382 undefined
qtloader.js:382 exception thrown: RuntimeError: abort(undefined). Build with -s ASSERTIONS=1 for more info.,RuntimeError: abort(undefined). Build with -s ASSERTIONS=1 for more info.
at abort (eval at completeLoadEmscriptenModule (http://localhost:8000/qtloader.js:443:14), <anonymous>:1:117796)
at _abort (eval at completeLoadEmscriptenModule (http://localhost:8000/qtloader.js:443:14), <anonymous>:1:216554)
at http://localhost:8000/tictoc.wasm:wasm-function[3658]:0x2471b4
at http://localhost:8000/tictoc.wasm:wasm-function[1752]:0xcd351
at http://localhost:8000/tictoc.wasm:wasm-function[7852]:0x569081
at http://localhost:8000/tictoc.wasm:wasm-function[10513]:0x7cac64
at http://localhost:8000/tictoc.wasm:wasm-function[16524]:0xced708
at http://localhost:8000/tictoc.wasm:wasm-function[16519]:0xcea4c0
at http://localhost:8000/tictoc.wasm:wasm-function[18745]:0xe1a292
at ret.<computed> (eval at completeLoadEmscriptenModule (http://localhost:8000/qtloader.js:443:14), <anonymous>:1:290380)
[Violation] 'setTimeout' handler took 478ms
問題はこれか
qt.qpa.plugin: Could not find the Qt platform plugin "wasm" in ""
qtloader.js:382 This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.
qtenv.ccでWasmのPluginを読み込むようにする
#include <QtCore/QtPlugin>
Q_IMPORT_PLUGIN(QWasmIntegrationPlugin)
Q_IMPORT_PLUGIN(QGifPlugin)
Q_IMPORT_PLUGIN(QICOPlugin)
Q_IMPORT_PLUGIN(QJpegPlugin)
というわけで実行してみると、main loopまわりでこける。これは直すの簡単で、Qtに新たなイベントループを作らせないように書き換えていくだけ。大変なんだけど。
Assertion failed: emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters.
qtloader.js:382 exception thrown: RuntimeError: abort(Assertion failed: emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters.). Build with -s ASSERTIONS=1 for more info.,RuntimeError: abort(Assertion failed: emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters.). Build with -s ASSERTIONS=1 for more info.
at abort (eval at completeLoadEmscriptenModule (http://localhost:8000/qtloader.js:443:14), <anonymous>:1:117798)
at assert (eval at completeLoadEmscriptenModule (http://localhost:8000/qtloader.js:443:14), <anonymous>:1:109209)
at setMainLoop (eval at completeLoadEmscriptenModule (http://localhost:8000/qtloader.js:443:14), <anonymous>:1:219868)
at _emscripten_set_main_loop_arg (eval at completeLoadEmscriptenModule (http://localhost:8000/qtloader.js:443:14), <anonymous>:1:325760)
at http://localhost:8000/tictoc.wasm:wasm-function[18076]:0xdc5783
at http://localhost:8000/tictoc.wasm:wasm-function[3277]:0x19d1b9
at http://localhost:8000/tictoc.wasm:wasm-function[4293]:0x27f911
at http://localhost:8000/tictoc.wasm:wasm-function[19550]:0xea3e76
at ret.<computed> (eval at completeLoadEmscriptenModule (http://localhost:8000/qtloader.js:443:14), <anonymous>:1:351095)
at invoke_ii (eval at completeLoadEmscriptenModule (http://localhost:8000/qtloader.js:443:14), <anonymous>:1:399596)
VM67:1 Uncaught RuntimeError: abort(Assertion failed: emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters.). Build with -s ASSERTIONS=1 for more info.
at abort (eval at completeLoadEmscriptenModule (qtloader.js:443:14), <anonymous>:1:117798)
at assert (eval at completeLoadEmscriptenModule (qtloader.js:443:14), <anonymous>:1:109209)
at setMainLoop (eval at completeLoadEmscriptenModule (qtloader.js:443:14), <anonymous>:1:219868)
at _emscripten_set_main_loop_arg (eval at completeLoadEmscriptenModule (qtloader.js:443:14), <anonymous>:1:325760)
at tictoc.wasm:0xdc5783
at tictoc.wasm:0x19d1b9
at tictoc.wasm:0x27f911
at tictoc.wasm:0xea3e76
at ret.<computed> (eval at completeLoadEmscriptenModule (qtloader.js:443:14), <anonymous>:1:351095)
at invoke_ii (eval at completeLoadEmscriptenModule (qtloader.js:443:14), <anonymous>:1:399596)
結構昔とメソッド名とか変わってて苦戦している。そしてスタックトレースが役に立たないので、ひたすらprintデバッグするしかない
とりあえず画面が表示されるところまで持ってきた
イベントループを避けるようなpatchを当てたので、アニメーションが動くところまできた。
しかし、どうにもicons.qrcで示されたsvgファイルがうまく読み込まれていない。
なので、このような殺風景な画面になっている。
OMNeT++6になった時点で元々png形式だったアイコンがsvgになったのが原因かもしれない。
pngに変換してicons.qrcでそのpngファイルを指定すると表示された。
SVGについてはQtSVGが必要らしいので、ビルドして使ってみるか
QtSvgをいれて、LDFlagsに追加して、Pluginをimportしたら動いた
-L/root/qtsvg/lib/ -L/root/qtsvg/plugins/iconengines -L/root/qtsvg/plugins/imageformats -lQt5Svg -lqsvgicon -lqsvg
diff --git a/src/qtenv/qtenv.cc b/src/qtenv/qtenv.cc
index 90d2574038..4cd986482d 100644
--- a/src/qtenv/qtenv.cc
+++ b/src/qtenv/qtenv.cc
@@ -111,6 +111,15 @@ void initFontsResource()
Q_INIT_RESOURCE(fonts);
}
+#include <emscripten.h>
+#include <QtCore/QtPlugin>
+Q_IMPORT_PLUGIN(QWasmIntegrationPlugin)
+Q_IMPORT_PLUGIN(QGifPlugin)
+Q_IMPORT_PLUGIN(QICOPlugin)
+Q_IMPORT_PLUGIN(QJpegPlugin)
+Q_IMPORT_PLUGIN(QSvgPlugin)
+Q_IMPORT_PLUGIN(QSvgIconPlugin)
+
namespace omnetpp {
namespace qtenv {
というわけで動くようになりしたとさ