Emscripten: emmake 生成 .js 文件

Posted

技术标签:

【中文标题】Emscripten: emmake 生成 .js 文件【英文标题】:Emscripten: emmake generating .js files 【发布时间】:2015-07-22 15:41:38 【问题描述】:

根据Emscripten Docs

Make 生成链接的 LLVM 位码。它不会在链接期间自动生成 javascript,因为所有文件都必须使用相同的优化和编译器选项进行编译——在从位码到 JavaScript 的最终转换中这样做是有意义的。

这很好,我想做什么。但是,运行 Emscripten 来编译 openjpeg .jp2 library 会生成 4 个 5-6mb 范围内的未压缩 (-O0) .js 文件和三个相同的字节码 .so 514kb 文件,它们似乎不包含我需要的代码.当我通过emcc 运行它们时,它们显示为 141kb,没有 _main 函数或任何可识别的东西,并且与其他 .js 文件的行为不同。

我需要更改哪些内容才能使用 emmake 命令而不是 .js 文件生成正确的字节码?

emcmake cmake 正常完成,然后emmake make 工作,但我没有选择尝试各种优化或emcc 通常提供的任何选项。

我在 Win 8 下的 vbox 中尝试在 Lubuntu 15.04 上进行此编译。这是除教程之外的第一个 emscripten 项目。我对 c 或 c++ 或一般编译也不是很熟悉(尽管我可以毫无问题地将这个项目编译成 Linux 应用程序)。

我知道 j2k.js,但我正在寻找 obj_compress,而不是 obj_decompress。

【问题讨论】:

【参考方案1】:

我不确定 emcmake 或 emmake 的使用,但我在一个基于 CMAKE 的 C++ 项目上工作,这是一个主要的可执行文件,曾经在 Linux 上编译为 x86_64 可执行文件,我转换为 emscriptem 以便部署它在 nginx 服务器上。

CMAKE 交叉编译 + 目标平台和输出 = 工具链文件 + 链接器标志 + 编译器标志

openjpeg.jp2 项目是一个 CMAKE C/C++ 程序。

在这里,您尝试使用 GCC 交叉编译 主机 linux x86 中的 C/C++ 库或可执行文件strong> 例如,也可以是 Windows + Visual C++ 编译器。

工具链文件

您需要一个 CMAKE 工具链文件,它会告诉 CMAKE 如何使用 emscriptem 工具,包括 emscriptem 编译器和生成 JS 或 WebAssembly 的链接器。

在此处获取 Emscriptem cmake 工具链文件示例 linux GCC x86: https://gist.github.com/romatou18/9f631147b5b26f980ab9669c375a6e3f

编译器标志

使用 CMAKE 项目时,请参阅 CMakeLists.txt 文件,以便根据选择的调试/发布构建类型(即 openjpeg.jp2 项目的 GCC 构建标志)查找/应用/修改编译器和链接器标志:李>

编译器标志示例: https://github.com/uclouvain/openjpeg/blob/172c8ae5cf230ff74b5814daf29e5b577aa30a9b/CMakeLists.txt#L200

同样,我不知道 emmake/emcmake 的细节,但如果您的项目是基于 CMAKE 的,工具链文件应该告诉 CMAKE 编译您的程序所需的所有信息。

Emscriptem 链接器标志:选择 Native JS 或 WebAssembly 输出

CMakelists.txt 指定 emscriptem 链接器标志并根据 JS_ONLY 选项选择 JS 或 WebAssembly 作为输出:

cmake_minimum_required(VERSION 3.6)
message( "Current dir: $CMAKE_CURRENT_LIST_DIR" )

#make sure it is all static
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
SET(BUILD_SHARED_LIBRARIES OFF)

option(JS_ONLY "Compiles to native JS (No WASM)" OFF)

add_executable( myProgram main.cpp)
target_link_libraries( myProgram $API_LIB)
target_compile_features(myProgram PRIVATE cxx_std_14)


if(JS_ONLY)
  message(STATUS "Setting compilation target to native JavaScript")
  set(CMAKE_EXECUTABLE_SUFFIX ".js")
  set_target_properties(myProgram PROPERTIES LINK_FLAGS "--emrun -s EXPORTED_FUNCTIONS='[_main]'")
else(JS_ONLY)
  message(STATUS "Setting compilation target to WASM")
  set(CMAKE_EXECUTABLE_SUFFIX ".wasm.js")
  set_target_properties(myProgram PROPERTIES LINK_FLAGS "--emrun -s WASM=1 -s BINARYEN_METHOD='native-wasm' -s EXPORTED_FUNCTIONS='[_main]' -s NO_EXIT_RUNTIME=1 -s EXTRA_EXPORTED_RUNTIME_METHODS=['ccall']")
endif(JS_ONLY)

#- Compiling to emscriptem/js output: PROPERTIES LINK_FLAGS set to --emrun -s 

#- Compiling to emscriptem/WASM => webAssembly output: PROPERTIES LINK_FLAGS set to --emrun -s WASM=1 -s BINARYEN_METHOD='native-wasm'


注意 WebAssembly 是您使用 EmscriptEm 将获得的最低输出级别,理论上应该比 JS 更紧凑。

自定义 Cmakelist.txt

在这个特定的项目上,重用我上面给出的示例 CMakeLists.txt 并对其进行自定义:

如上所述使用 emscriptem 目标上的链接标志设置您的 emscriptem 目标
set_target_properties(... PROPERTIES LINK_FLAGS "--emrun -s <emscript em link flags as described above>)
根据项目的源语言为发布版本 C AND OR C++ 配置发布版本编译器标志,C 标志示例如下:
set(CMAKE_C_FLAGS_DEBUG "-O0 -ggdb -Wall -Wunused-variable -Wno-unused-parameter -fno-inline ... etc ...etc ...")
set(CMAKE_C_FLAGS_RELEASE "-O2 -Wno-format-security -Wno-format-nonliteral -Wall -Wunused-variable -Wno-unused-parameter")
set(CMAKE_C_FLAGS "$CMAKE_C_FLAGS [+ optional extra flags for both here...]"

运行 cmake 配置

现在是时候使用工具链文件了:

使用所需的构建类型运行 cmake,并指定告诉 CMAKE 如何使用 emscriptem 的工具链文件,取自上述要点:
cmake -DCMAKE_BUILD_TYPE:string="Release" -DCMAKE_TOOLCHAIN_FILE=Toolchain-Emscripten.cmake src/"

将 src/ 替换为源目录。

我还没有尝试在 openjpeg 项目上运行它,但我认为这应该让你走上正轨。对此进行迭代,直到它起作用。我有一个工作库和执行程序正是使用这个,不再;-)

这又是一个基于 CMAKE 的项目,它看起来设计精美并且看起来是模块化的,因此我会坚持使用 CMAKE + 交叉编译工具链文件并将 make/emmake 的细节留给...... CMAKE,除非你真的没有其他的选择。

希望这会有所帮助!

罗曼

【讨论】:

以上是关于Emscripten: emmake 生成 .js 文件的主要内容,如果未能解决你的问题,请参考以下文章

使用 emscripten 生成 python.cc.js

将文件名传递给 Emscripten 生成的 js 作为参数

如何使用 es6 导入加载 emscripten 生成的模块?

Emscripten 网页js调用C++ (ffmpeg)

Emscripten 网页js调用C++ (ffmpeg)

Emscripten 网页js调用C++ (ffmpeg)