From 0c3aa5ef25cf893f91cc976b0bbfdd441e24e9e2 Mon Sep 17 00:00:00 2001 From: Gregory Lirent Date: Mon, 22 Jun 2026 15:52:39 +0300 Subject: [PATCH] Build a shared library and ship it as Debian packages Factor the source list into an OBJECT library so the same objects back both the existing static lib and a new shared libvmie.so (SONAME from the project version; the version comes from the tag, falling back to a cached default). Add install rules and a CPack DEB config that produce two packages: libvmie0 (the runtime .so + SONAME symlink) and libvmie-dev (public headers under include/vmie + the linker symlink), with the dev package depending on the exact runtime version. Add a CI job that, on a v* tag, builds the shared library, runs cpack, and uploads both .deb files to the Gitea Debian package registry. --- .gitea/workflows/release.yml | 55 ++++++++++++++++++++++++++ CMakeLists.txt | 76 ++++++++++++++++++++++++++++++++---- 2 files changed, 124 insertions(+), 7 deletions(-) diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 9a57362..276369c 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -70,3 +70,58 @@ jobs: curl -fsSL -X POST -H "$auth" \ -F "attachment=@dist/${asset};type=application/zip" \ "${api}/releases/${rid}/assets?name=${asset}" + + deb: + runs-on: ubuntu-latest + container: + image: node:20-bookworm-slim + defaults: + run: + shell: bash + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install toolchain + run: | + apt-get update + apt-get install -y --no-install-recommends \ + cmake make gcc libc6-dev dpkg-dev \ + gcc-mingw-w64-x86-64 ca-certificates curl + + - name: Configure + env: + TAG: ${{ github.ref_name }} + run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DVMIE_VERSION=${TAG#v} + + - name: Build shared library + run: cmake --build build -j --target vmie_shared + + - name: Package + run: | + set -euo pipefail + (cd build && cpack -G DEB) + ls -l build/*.deb + + - name: Publish to Debian registry + env: + TOKEN: ${{ secrets.PUBLISH_TOKEN }} # requires scope: package:write + SERVER: ${{ github.server_url }} + OWNER: ${{ github.repository_owner }} + DISTRIBUTION: stable + COMPONENT: main + run: | + set -euo pipefail + url="${SERVER}/api/packages/${OWNER}/debian/pool/${DISTRIBUTION}/${COMPONENT}/upload" + auth="Authorization: token ${TOKEN}" + for deb in build/*.deb; do + # 201 Created = uploaded; 409 Conflict = this version already present (re-run). + # Both are success; anything else fails. Do not use curl -f (it would fail 409). + code=$(curl -s -o /dev/null -w '%{http_code}' \ + -X PUT -H "$auth" -T "$deb" "$url") + echo "$deb -> HTTP $code" + if [ "$code" != 201 ] && [ "$code" != 409 ]; then + echo "upload failed: $deb (HTTP $code)" >&2 + exit 1 + fi + done diff --git a/CMakeLists.txt b/CMakeLists.txt index 16be044..2150bf4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,15 +1,19 @@ cmake_minimum_required(VERSION 3.18) # find_program(... REQUIRED) -project(vmi-engine C) + +set(VMIE_VERSION "0.1.4" CACHE STRING "Library version (MAJOR.MINOR.PATCH); CI passes the tag") +project(vmi-engine VERSION ${VMIE_VERSION} LANGUAGES C) set(CMAKE_C_STANDARD 17) # generation B uses no C23 feature set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_EXTENSIONS ON) # deliberate: strnlen (POSIX) + void* arithmetic (GNU) set(CMAKE_POSITION_INDEPENDENT_CODE ON) # -fPIC on all objects: static lib stays linkable into a shared object +include(GNUInstallDirs) + option(VMIE_LTO "Enable LTO" OFF) # build-only; shipped default is -O2, no LTO -# ---- host: VMI core as a static library --------------------------------- -add_library(vmie STATIC +# ---- host: VMI core objects (single owner of the source list) ----------- +add_library(vmie_obj OBJECT src/core/gpa.c src/engine/gva.c src/engine/sigphys.c @@ -27,15 +31,32 @@ add_library(vmie STATIC src/handlers/x86dec.c src/handlers/pmap.c src/handlers/snapdiff.c) -target_include_directories(vmie +target_include_directories(vmie_obj PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include # public API: include/*.h PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/core/include # private: core.h ${CMAKE_CURRENT_SOURCE_DIR}/src/engine/include # private: engine-arch.h, pe.h ${CMAKE_CURRENT_SOURCE_DIR}/src/engine/win32) # private: engine-win32.h, contract.h -target_compile_options(vmie PRIVATE -O2 -Wall -Wextra) +target_compile_options(vmie_obj PRIVATE -O2 -Wall -Wextra) if(VMIE_LTO) - target_compile_options(vmie PRIVATE -flto) - target_link_options(vmie PRIVATE -flto) + target_compile_options(vmie_obj PRIVATE -flto) + target_link_options(vmie_obj PRIVATE -flto) +endif() + +# ---- host: static library (in-tree consumers: CLIs + test) -------------- +# $ carries object files only, not usage requirements: +# re-declare the PUBLIC include scope so vmie_cli/vmie_scan still see include/. +add_library(vmie STATIC $) +target_include_directories(vmie PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) + +# ---- host: shared library (external delivery: libvmie.so.*) ------------- +add_library(vmie_shared SHARED $) +target_include_directories(vmie_shared PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) +set_target_properties(vmie_shared PROPERTIES + OUTPUT_NAME vmie + SOVERSION ${PROJECT_VERSION_MAJOR} + VERSION ${PROJECT_VERSION}) +if(VMIE_LTO) + target_link_options(vmie_shared PRIVATE -flto) endif() # ---- host: CLI demonstrator over the library ---------------------------- @@ -61,3 +82,44 @@ add_custom_command( COMMENT "Cross-compiling vmie-startup.exe (mingw-w64, x86-64)" VERBATIM) add_custom_target(vmie-startup ALL DEPENDS ${VMIE_STARTUP}) + +# ---- install: shared library + public headers --------------------------- +# Versioned file + SONAME symlink -> runtime; unversioned linker symlink -> dev. +install(TARGETS vmie_shared + LIBRARY + DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT runtime + NAMELINK_COMPONENT dev) +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/vmie + COMPONENT dev + FILES_MATCHING PATTERN "*.h") + +# ---- package: two Debian packages (runtime + dev) ----------------------- +set(CPACK_GENERATOR "DEB") +set(CPACK_DEB_COMPONENT_INSTALL ON) +set(CPACK_COMPONENTS_ALL runtime dev) +set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION}) + +# component -> Debian package name (Debian shared-library convention) +set(CPACK_DEBIAN_RUNTIME_PACKAGE_NAME "libvmie${PROJECT_VERSION_MAJOR}") +set(CPACK_DEBIAN_DEV_PACKAGE_NAME "libvmie-dev") + +set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64") +set(VMIE_DEB_MAINTAINER "Gregory Lirent " + CACHE STRING "Debian package Maintainer field") +set(CPACK_DEBIAN_PACKAGE_MAINTAINER "${VMIE_DEB_MAINTAINER}") +set(CPACK_DEBIAN_PACKAGE_SECTION "libs") +set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional") +set(CPACK_DEBIAN_FILE_NAME "DEB-DEFAULT") + +set(CPACK_COMPONENT_RUNTIME_DESCRIPTION + "VM introspection engine (Windows-guest memory introspection) - shared library") +set(CPACK_COMPONENT_DEV_DESCRIPTION + "VM introspection engine (Windows-guest memory introspection) - development files") + +# dev depends on the exact runtime version; runtime libc dependency via shlibdeps +set(CPACK_DEBIAN_DEV_PACKAGE_DEPENDS "libvmie${PROJECT_VERSION_MAJOR} (= ${PROJECT_VERSION})") +set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) + +include(CPack)