如何将库编译成可以从 JavaScript 代码调用的 WebAssembly?

How can I compile a library into WebAssembly that can be called from JavaScript code?

我正在尝试使用 WASM,我想将图片编码为 WebP 以学习 WASM。

我正在尝试编译 libwebp into a single mjs file. Specifically, the encoding utility。我正在使用 Emscripten,因为我想在我的 WebAssembly 网络应用程序中 运行 这个。我正在编译它以作为 <script src=foobar> 文件导入。

这是我目前拥有的:

two@develop ...libwebp/src/enc (main)
% emcc src/enc/webp_enc.c -o src/foo.mjs -s ENVIRONMENT='web' -s SINGLE_FILE=1  -s USE_ES6_IMPORT_META=0 -O3 

但我认为输入文件 src/enc/webp_enc.c 不是正确的输入文件。有谁知道我应该使用哪个导入文件?另外,我可能需要做的任何其他我遗漏的事情吗?

您将很难尝试通过在单个翻译单元上调用 Emscripten 编译器来编译整个库;编码器并不完全包含在一个文件中。您需要使用构建系统来构建完整的库。

幸运的是,将库移植到 WebAssembly 的大部分工作已经完成;甚至还有 a README file with instructions on building a demo program,它使用 SDL 解码文件并将其呈现为 <canvas>。您可以查看 CMakeLists.txt 中的演示如何设置并根据自己的喜好进行修改,以便从库中导出编码器而不是解码器。

不过,您最好创建自己的 CMake 项目,imports the encoder library 并导出您希望从 JavaScript 代码中调用的函数。假设您将库放在 libwebp/ 子目录中,创建一个 CMakeLists.txt,内容如下:

project(mywebpenc)
cmake_minimum_required(VERSION 3.22)

add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/libwebp)

add_executable(mywebpenc ${CMAKE_CURRENT_SOURCE_DIR}/mywebpenc.c)
target_include_directories(mywebpenc PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
target_include_directories(mywebpenc PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/libwebp/src)
target_compile_definitions(mywebpenc PUBLIC EMSCRIPTEN)
target_link_libraries(mywebpenc webpencode webpdsp webputils)

set_target_properties(mywebpenc
    PROPERTIES LINK_FLAGS "-s WASM=1 \
        -s EXPORTED_FUNCTIONS='[\"_mywebpenc_encode\"]' -s INVOKE_RUN=0 \
        -s EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'")

然后将上面的一个函数命名为mywebpenc_encode,把你要导出到JS的接口放到mywebpenc.c中。作为概念验证,我尝试了一个简单的存根:

#include <webp/encode.h>

extern size_t mywebpenc_encode(
    const uint8_t* rgb, int width, int height, int stride,
    float quality_factor, uint8_t** output)
{
    return WebPEncodeRGB(rgb, width, height, stride, quality_factor, output);
}

使用 emcmake cmake . && make mywebpenc 构建项目。您将获得两个文件,mywebpenc.jsmywebpenc.wasm,您应该可以 interface with like with any other Emscripten library.