From 830932290f900903a8a629e68c43db4ded036e64 Mon Sep 17 00:00:00 2001 From: Prateek99-s <145468640+Prateek99-s@users.noreply.github.com> Date: Thu, 22 Oct 2026 09:59:20 +0000 Subject: [PATCH] feat: standalone build and migrate wasmedge_process and wasmedge_image (#24, #35, #39) - Implement standalone CMake build against released WasmEdge SDK 0.17.2 (#24) - Migrate wasmedge_process with unit tests and GitHub Actions workflow (#39) - Migrate wasmedge_image with STB dependency, tests, and CI workflow (#35) - Disable unimported wasi_logging test target per #24 review notes - Document building, testing, and SDK release upgrade policy in README.md Signed-off-by: Prateek99-s <145468640+Prateek99-s@users.noreply.github.com> --- .github/scripts/wasmedge_image/build.sh | 22 ++ .github/scripts/wasmedge_process/build.sh | 22 ++ .github/workflows/build-wasmedge_image.yml | 38 ++++ .github/workflows/build-wasmedge_process.yml | 38 ++++ CMakeLists.txt | 56 +++++ README.md | 67 ++++++ cmake/Helper.cmake | 213 +++++++++++++++++++ test/plugins/CMakeLists.txt | 8 +- test/plugins/unittest/CMakeLists.txt | 6 + 9 files changed, 467 insertions(+), 3 deletions(-) create mode 100644 .github/scripts/wasmedge_image/build.sh create mode 100644 .github/scripts/wasmedge_process/build.sh create mode 100644 .github/workflows/build-wasmedge_image.yml create mode 100644 .github/workflows/build-wasmedge_process.yml create mode 100644 CMakeLists.txt create mode 100644 cmake/Helper.cmake diff --git a/.github/scripts/wasmedge_image/build.sh b/.github/scripts/wasmedge_image/build.sh new file mode 100644 index 00000000..50ce80be --- /dev/null +++ b/.github/scripts/wasmedge_image/build.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright The WasmEdge Authors + +set -e + +# Load WasmEdge environment if installed via install.sh +if [ -f "$HOME/.wasmedge/env" ]; then + # shellcheck source=/dev/null + source "$HOME/.wasmedge/env" +fi + +BUILD_DIR="${BUILD_DIR:-build}" + +cmake -B "${BUILD_DIR}" \ + -DCMAKE_BUILD_TYPE=Release \ + -DWASMEDGE_PLUGIN_IMAGE=ON \ + -DWASMEDGE_BUILD_TESTS=ON + +cmake --build "${BUILD_DIR}" --config Release -j "$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)" + +ctest --test-dir "${BUILD_DIR}" -R wasmedgeImageTests --output-on-failure diff --git a/.github/scripts/wasmedge_process/build.sh b/.github/scripts/wasmedge_process/build.sh new file mode 100644 index 00000000..ddd3c6c5 --- /dev/null +++ b/.github/scripts/wasmedge_process/build.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright The WasmEdge Authors + +set -e + +# Load WasmEdge environment if installed via install.sh +if [ -f "$HOME/.wasmedge/env" ]; then + # shellcheck source=/dev/null + source "$HOME/.wasmedge/env" +fi + +BUILD_DIR="${BUILD_DIR:-build}" + +cmake -B "${BUILD_DIR}" \ + -DCMAKE_BUILD_TYPE=Release \ + -DWASMEDGE_PLUGIN_PROCESS=ON \ + -DWASMEDGE_BUILD_TESTS=ON + +cmake --build "${BUILD_DIR}" --config Release -j "$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)" + +ctest --test-dir "${BUILD_DIR}" -R wasmedgeProcessTests --output-on-failure diff --git a/.github/workflows/build-wasmedge_image.yml b/.github/workflows/build-wasmedge_image.yml new file mode 100644 index 00000000..4d338577 --- /dev/null +++ b/.github/workflows/build-wasmedge_image.yml @@ -0,0 +1,38 @@ +--- +name: build-wasmedge_image + +on: + push: + branches: [main] + pull_request: + branches: [main] + paths: + - '.github/workflows/build-wasmedge_image.yml' + - '.github/scripts/wasmedge_image/**' + - 'plugins/wasmedge_image/**' + - 'test/plugins/wasmedge_image/**' + - 'cmake/**' + - 'CMakeLists.txt' + +permissions: + contents: read + +jobs: + build: + name: ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-22.04, ubuntu-24.04, macos-13, macos-14] + + steps: + - uses: actions/checkout@v7 + + - name: Install WasmEdge + run: | + curl -sSf https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | bash -s -- -v 0.17.2 + + - name: Build and Test wasmedge_image + run: | + bash .github/scripts/wasmedge_image/build.sh diff --git a/.github/workflows/build-wasmedge_process.yml b/.github/workflows/build-wasmedge_process.yml new file mode 100644 index 00000000..b2c68d5e --- /dev/null +++ b/.github/workflows/build-wasmedge_process.yml @@ -0,0 +1,38 @@ +--- +name: build-wasmedge_process + +on: + push: + branches: [main] + pull_request: + branches: [main] + paths: + - '.github/workflows/build-wasmedge_process.yml' + - '.github/scripts/wasmedge_process/**' + - 'plugins/wasmedge_process/**' + - 'test/plugins/wasmedge_process/**' + - 'cmake/**' + - 'CMakeLists.txt' + +permissions: + contents: read + +jobs: + build: + name: ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-22.04, ubuntu-24.04] + + steps: + - uses: actions/checkout@v7 + + - name: Install WasmEdge + run: | + curl -sSf https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | bash -s -- -v 0.17.2 + + - name: Build and Test wasmedge_process + run: | + bash .github/scripts/wasmedge_process/build.sh diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..e974be73 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright The WasmEdge Authors + +cmake_minimum_required(VERSION 3.16) +project(wasmedge_plugins C CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +include(Helper) + +# Plugin build options (default: OFF, per Issue #24) +option(WASMEDGE_PLUGIN_PROCESS "Build wasmedge_process plugin" OFF) +option(WASMEDGE_PLUGIN_IMAGE "Build wasmedge_image plugin" OFF) +option(WASMEDGE_PLUGIN_ZLIB "Build wasmedge_zlib plugin" OFF) +option(WASMEDGE_PLUGIN_WASI_CRYPTO "Build wasi_crypto plugin" OFF) +option(WASMEDGE_PLUGIN_WASI_HTTP "Build wasi_http plugin" OFF) +option(WASMEDGE_PLUGIN_WASI_NN_BACKEND "Build wasi_nn plugin" OFF) +option(WASMEDGE_PLUGIN_WASI_POLL "Build wasi_poll plugin" OFF) +option(WASMEDGE_PLUGIN_WASM_BPF "Build wasm_bpf plugin" OFF) +option(WASMEDGE_PLUGIN_FFMPEG "Build wasmedge_ffmpeg plugin" OFF) +option(WASMEDGE_PLUGIN_OCR "Build wasmedge_ocr plugin" OFF) +option(WASMEDGE_PLUGIN_OPENCVMINI "Build wasmedge_opencvmini plugin" OFF) +option(WASMEDGE_PLUGIN_STABLEDIFFUSION "Build wasmedge_stablediffusion plugin" OFF) +option(WASMEDGE_PLUGIN_TENSORFLOW "Build wasmedge_tensorflow plugin" OFF) +option(WASMEDGE_PLUGIN_TENSORFLOWLITE "Build wasmedge_tensorflowlite plugin" OFF) +option(WASMEDGE_PLUGIN_UNITTESTS "Build plugin loader unit tests" OFF) + +option(WASMEDGE_BUILD_TESTS "Build plugin tests" OFF) +option(WASMEDGE_LINK_PLUGINS_STATIC "Link plugins statically against WasmEdge" OFF) + +# Locate WasmEdge SDK and headers +wasmedge_find_sdk() + +# Build enabled plugins +add_subdirectory(plugins) + +# Build tests if requested +if(WASMEDGE_BUILD_TESTS) + enable_testing() + add_compile_definitions(FMT_HEADER_ONLY=1) + find_package(GTest QUIET) + if(NOT TARGET GTest::gtest) + include(FetchContent) + FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG v1.14.0 + GIT_SHALLOW TRUE + ) + FetchContent_MakeAvailable(googletest) + endif() + set(GTEST_BOTH_LIBRARIES GTest::gtest GTest::gtest_main) + add_subdirectory(test/plugins) +endif() diff --git a/README.md b/README.md index 4c025c74..11914185 100644 --- a/README.md +++ b/README.md @@ -1 +1,68 @@ # WasmEdge C++ Plugins + +This repository hosts standalone C++ plugins for [WasmEdge](https://github.com/WasmEdge/WasmEdge). + +Plugins are built standalone against a released WasmEdge SDK rather than tracking unreleased WasmEdge `master`. + +## Plugins + +| Plugin | Build Option | Platforms | Status | +| :--- | :--- | :--- | :--- | +| `wasmedge_image` | `-DWASMEDGE_PLUGIN_IMAGE=ON` | Linux, macOS | Migrated | +| `wasmedge_process` | `-DWASMEDGE_PLUGIN_PROCESS=ON` | Linux | Migrated | + +## Prerequisites + +1. **CMake** 3.16 or later (3.24+ recommended) +2. **C++17 Compiler** (GCC, Clang, or MSVC) +3. **WasmEdge SDK** (version 0.17.2 or later) + +To install WasmEdge: +```bash +curl -sSf https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | bash -s -- -v 0.17.2 +``` + +## Building Plugins + +Plugins are configured with all `WASMEDGE_PLUGIN_*` options set to `OFF` by default. Enable only the plugins you wish to build: + +```bash +# Build wasmedge_process +cmake -B build -DWASMEDGE_PLUGIN_PROCESS=ON +cmake --build build + +# Build wasmedge_image +cmake -B build -DWASMEDGE_PLUGIN_IMAGE=ON +cmake --build build +``` + +The compiled plugin shared libraries will be placed under `build/plugins//`. + +### Locating the WasmEdge SDK + +The build system searches for the WasmEdge library and headers in common installation directories (`$HOME/.wasmedge`, `/usr/local`, `/usr`). + +You can explicitly provide custom paths using CMake variables or environment variables: +- `WASMEDGE_DIR`: Path to the WasmEdge installation prefix (e.g. `~/.wasmedge`) +- `WASMEDGE_LIB_DIR`: Path to directory containing `libwasmedge.so` / `libwasmedge.dylib` +- `WASMEDGE_INCLUDE_DIR`: Path to WasmEdge headers directory + +If headers are not found locally, CMake will automatically fetch headers for the pinned WasmEdge release. + +## Running Tests + +To build and execute plugin unit tests: + +```bash +cmake -B build \ + -DWASMEDGE_PLUGIN_PROCESS=ON \ + -DWASMEDGE_PLUGIN_IMAGE=ON \ + -DWASMEDGE_BUILD_TESTS=ON + +cmake --build build +ctest --test-dir build --output-on-failure +``` + +## Upgrade Policy + +Plugins in this repository sync to new WasmEdge APIs **only when WasmEdge cuts an official release**. The minimum target release is pinned via `WASMEDGE_PINNED_VERSION` in `cmake/Helper.cmake` (currently `0.17.2`). Maintainers should not track or depend on unreleased `master` branch changes. diff --git a/cmake/Helper.cmake b/cmake/Helper.cmake new file mode 100644 index 00000000..4737726d --- /dev/null +++ b/cmake/Helper.cmake @@ -0,0 +1,213 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright The WasmEdge Authors + +if(POLICY CMP0169) + cmake_policy(SET CMP0169 OLD) +endif() + +include(CMakePackageConfigHelpers) +include(GNUInstallDirs) +include(FetchContent) + +# Pinned WasmEdge release version for plugins +set(WASMEDGE_PINNED_VERSION "0.17.2" CACHE STRING "Target WasmEdge release version") + +# Target setup helper +function(wasmedge_setup_target target) + set_target_properties(${target} PROPERTIES + CXX_STANDARD 17 + CXX_EXTENSIONS OFF + CXX_VISIBILITY_PRESET hidden + ENABLE_EXPORTS ON + POSITION_INDEPENDENT_CODE ON + VISIBILITY_INLINES_HIDDEN ON + BUILD_RPATH_USE_ORIGIN ON + MACOSX_RPATH ON + ) + if(CMAKE_SYSTEM_NAME MATCHES "Linux") + set_target_properties(${target} PROPERTIES + INSTALL_RPATH "$ORIGIN" + ) + elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin") + set_target_properties(${target} PROPERTIES + INSTALL_RPATH "@loader_path" + ) + endif() +endfunction() + +function(wasmedge_add_library target) + add_library(${target} ${ARGN}) + wasmedge_setup_target(${target}) +endfunction() + +function(wasmedge_add_executable target) + add_executable(${target} ${ARGN}) + wasmedge_setup_target(${target}) + if(CMAKE_SYSTEM_NAME MATCHES "Linux") + set_target_properties(${target} PROPERTIES + INSTALL_RPATH "$ORIGIN" + ) + elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin") + set_target_properties(${target} PROPERTIES + INSTALL_RPATH "@executable_path" + ) + endif() +endfunction() + +# stb_image dependency helper for wasmedge_image +function(wasmedge_setup_stb_image) + if(TARGET wasmedgeDepsSTBImage) + return() + endif() + message(STATUS "Configuring stb_image dependency...") + FetchContent_Declare( + stb + GIT_REPOSITORY https://github.com/nothings/stb.git + GIT_TAG 31c1ad37456438565541f4919958214b6e762fb4 # stb_image v2.30 + GIT_SHALLOW FALSE + ) + FetchContent_MakeAvailable(stb) + add_library(wasmedgeDepsSTBImage INTERFACE) + target_include_directories(wasmedgeDepsSTBImage SYSTEM INTERFACE ${stb_SOURCE_DIR}) +endfunction() + +# Locate WasmEdge SDK and headers +macro(wasmedge_find_sdk) + # 1. Locate WasmEdge shared library + find_library(WASMEDGE_LIBRARY + NAMES wasmedge + HINTS + ${WASMEDGE_LIB_DIR} + $ENV{WASMEDGE_LIB_DIR} + $ENV{WASMEDGE_DIR}/lib + $ENV{HOME}/.wasmedge/lib + /usr/local/lib + /usr/lib + ) + + if(NOT WASMEDGE_LIBRARY) + message(FATAL_ERROR "Could not find libwasmedge. Please install WasmEdge or set WASMEDGE_LIB_DIR.") + endif() + message(STATUS "Found WasmEdge shared library: ${WASMEDGE_LIBRARY}") + + # Define wasmedge_shared and wasmedgeCAPI imported targets + if(NOT TARGET wasmedge_shared) + add_library(wasmedge_shared UNKNOWN IMPORTED) + set_target_properties(wasmedge_shared PROPERTIES + IMPORTED_LOCATION "${WASMEDGE_LIBRARY}" + ) + endif() + if(NOT TARGET wasmedgeCAPI) + add_library(wasmedgeCAPI UNKNOWN IMPORTED) + set_target_properties(wasmedgeCAPI PROPERTIES + IMPORTED_LOCATION "${WASMEDGE_LIBRARY}" + ) + endif() + + # 2. Locate or fetch WasmEdge C++ headers + set(WASMEDGE_HEADER_FOUND FALSE) + if(WASMEDGE_INCLUDE_DIR) + if(EXISTS "${WASMEDGE_INCLUDE_DIR}/plugin/plugin.h") + set(WASMEDGE_HEADER_FOUND TRUE) + set(WASMEDGE_CPP_INCLUDE_DIR "${WASMEDGE_INCLUDE_DIR}") + endif() + endif() + + if(NOT WASMEDGE_HEADER_FOUND) + # Check common locations + find_path(CANDIDATE_INCLUDE_DIR + NAMES "plugin/plugin.h" + HINTS + $ENV{WASMEDGE_INCLUDE_DIR} + $ENV{WASMEDGE_DIR}/include + $ENV{HOME}/.wasmedge/include + /usr/local/include + /usr/include + ) + if(CANDIDATE_INCLUDE_DIR) + set(WASMEDGE_HEADER_FOUND TRUE) + set(WASMEDGE_CPP_INCLUDE_DIR "${CANDIDATE_INCLUDE_DIR}") + endif() + endif() + + if(NOT WASMEDGE_HEADER_FOUND) + message(STATUS "Fetching WasmEdge ${WASMEDGE_PINNED_VERSION} headers...") + FetchContent_Declare( + wasmedge_headers + GIT_REPOSITORY https://github.com/WasmEdge/WasmEdge.git + GIT_TAG ${WASMEDGE_PINNED_VERSION} + GIT_SHALLOW TRUE + ) + FetchContent_GetProperties(wasmedge_headers) + if(NOT wasmedge_headers_POPULATED) + FetchContent_Populate(wasmedge_headers) + endif() + set(WASMEDGE_CPP_INCLUDE_DIR "${wasmedge_headers_SOURCE_DIR}/include") + endif() + message(STATUS "Using WasmEdge headers from: ${WASMEDGE_CPP_INCLUDE_DIR}") + + # 3. Locate WasmEdge C API headers + find_path(WASMEDGE_C_INCLUDE_DIR + NAMES "wasmedge/wasmedge.h" "wasmedge/enum_configure.h" + HINTS + ${WASMEDGE_INCLUDE_DIR} + $ENV{WASMEDGE_INCLUDE_DIR} + $ENV{WASMEDGE_DIR}/include + $ENV{HOME}/.wasmedge/include + /usr/local/include + /usr/include + ) + if(WASMEDGE_C_INCLUDE_DIR) + message(STATUS "Using WasmEdge C API headers from: ${WASMEDGE_C_INCLUDE_DIR}") + endif() + + # 4. Generate version.h and config.h in binary dir + set(WASMEDGE_GEN_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/gen_include") + file(MAKE_DIRECTORY "${WASMEDGE_GEN_INCLUDE_DIR}/common") + if(NOT EXISTS "${WASMEDGE_GEN_INCLUDE_DIR}/common/version.h") + file(WRITE "${WASMEDGE_GEN_INCLUDE_DIR}/common/version.h" +"// Generated by WasmEdge cpp-plugins standalone build +#pragma once +#include +#include +namespace WasmEdge { +using namespace std::literals::string_view_literals; +static inline std::string_view kVersionString [[maybe_unused]] = \"${WASMEDGE_PINNED_VERSION}\"sv; +static inline std::string_view kGlobalPluginDir [[maybe_unused]] = \"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/wasmedge\"sv; +static inline constexpr const uint32_t kPluginCurrentAPIVersion [[maybe_unused]] = 5; +} // namespace WasmEdge +" + ) + endif() + + if(NOT EXISTS "${WASMEDGE_GEN_INCLUDE_DIR}/common/config.h") + file(WRITE "${WASMEDGE_GEN_INCLUDE_DIR}/common/config.h" +"// Generated by WasmEdge cpp-plugins standalone build +#pragma once +#include +namespace WasmEdge { +using namespace std::literals::string_view_literals; +#define HAVE_MMAP 1 +#define HAVE_PWD_H 1 +} // namespace WasmEdge +" + ) + endif() + + # 5. Define wasmedgePlugin interface target with BOTH properties set + if(NOT TARGET wasmedgePlugin) + add_library(wasmedgePlugin INTERFACE) + set(WASMEDGE_ALL_INCLUDES + "${WASMEDGE_GEN_INCLUDE_DIR}" + "${WASMEDGE_CPP_INCLUDE_DIR}" + "${WASMEDGE_CPP_INCLUDE_DIR}/api" + ) + if(WASMEDGE_C_INCLUDE_DIR) + list(APPEND WASMEDGE_ALL_INCLUDES "${WASMEDGE_C_INCLUDE_DIR}") + endif() + set_target_properties(wasmedgePlugin PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${WASMEDGE_ALL_INCLUDES}" + INCLUDE_DIRECTORIES "${WASMEDGE_ALL_INCLUDES}" + ) + endif() +endmacro() diff --git a/test/plugins/CMakeLists.txt b/test/plugins/CMakeLists.txt index 7ead52f7..06965c61 100644 --- a/test/plugins/CMakeLists.txt +++ b/test/plugins/CMakeLists.txt @@ -6,8 +6,8 @@ if(WASMEDGE_PLUGIN_WASI_CRYPTO) add_subdirectory(wasi_crypto) endif() -# WASI plug-in: WASI-Logging proposal. -add_subdirectory(wasi_logging) +# WASI plug-in: WASI-Logging proposal (disabled: target not imported in cpp-plugins per Issue #24). +# add_subdirectory(wasi_logging) # WASI plug-in: WASI-NN proposal with backends. if(WASMEDGE_PLUGIN_WASI_NN_BACKEND) @@ -100,4 +100,6 @@ if(WASMEDGE_PLUGIN_ZLIB) endif() # Plug-in unit tests. -add_subdirectory(unittest) +if(WASMEDGE_PLUGIN_UNITTESTS) + add_subdirectory(unittest) +endif() diff --git a/test/plugins/unittest/CMakeLists.txt b/test/plugins/unittest/CMakeLists.txt index 8a0e2ad5..07cc7cf6 100644 --- a/test/plugins/unittest/CMakeLists.txt +++ b/test/plugins/unittest/CMakeLists.txt @@ -23,6 +23,12 @@ target_compile_options(wasmedgePluginTestModuleC -DWASMEDGE_PLUGIN ) +target_include_directories(wasmedgePluginTestModuleC + PUBLIC + $ + ${CMAKE_CURRENT_SOURCE_DIR} +) + # The test plugin module in C++ API wasmedge_add_library(wasmedgePluginTestModuleCPP SHARED