diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7a3b26411..237e5a749 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -446,6 +446,80 @@ jobs: cd ${{github.workspace}}/build ctest --parallel --output-on-failure + # ============================================================================ + # vcpkg integration + # ============================================================================ + vcpkg-integration: + strategy: + fail-fast: false + matrix: + os: [ ubuntu-latest, macos-latest, windows-latest ] + feature: [ "default", "static-shim" ] + runs-on: ${{ matrix.os }} + name: vcpkg - ${{ matrix.os }} ${{ matrix.feature }} + steps: + - uses: actions/checkout@v4 + + - name: Bootstrap vcpkg + shell: bash + run: | + git clone https://github.com/microsoft/vcpkg.git "${{ runner.temp }}/vcpkg" --depth 1 + if [ "$RUNNER_OS" = "Windows" ]; then + "${{ runner.temp }}/vcpkg/bootstrap-vcpkg.bat" -disableMetrics + else + "${{ runner.temp }}/vcpkg/bootstrap-vcpkg.sh" -disableMetrics + fi + + - name: Create overlay port pointing at local source + shell: bash + run: | + overlay="${{ runner.temp }}/overlay/snmalloc" + mkdir -p "$overlay" + # Copy the real port files + cp ports/snmalloc/vcpkg.json "$overlay/" + cp ports/snmalloc/usage "$overlay/" + # Normalize workspace path to forward slashes for CMake (Windows compat) + ws_path=$(echo "${{ github.workspace }}" | sed 's|\\|/|g') + # Rewrite portfile to use local source instead of vcpkg_from_github + { + echo 'if(NOT "static-shim" IN_LIST FEATURES)' + echo ' set(VCPKG_BUILD_TYPE release)' + echo 'endif()' + echo '' + echo "set(SOURCE_PATH \"${ws_path}\")" + echo '' + # Keep everything from vcpkg_check_features onwards (see comment in + # ports/snmalloc/portfile.cmake documenting this coupling) + sed -n '/^vcpkg_check_features/,$ p' ports/snmalloc/portfile.cmake + } > "$overlay/portfile.cmake" + + - name: Install snmalloc via vcpkg + shell: bash + # Run from runner.temp to avoid the workspace vcpkg.json triggering + # manifest mode (which forbids positional package arguments). + working-directory: ${{ runner.temp }} + run: | + features="" + if [ "${{ matrix.feature }}" = "static-shim" ]; then + features="[static-shim]" + fi + "${{ runner.temp }}/vcpkg/vcpkg" install "snmalloc${features}" \ + --overlay-ports="${{ runner.temp }}/overlay" + + - name: Build consumer project + shell: bash + run: | + cmake -B "${{ runner.temp }}/consumer-build" \ + -S test/vcpkg-consumer \ + -DCMAKE_TOOLCHAIN_FILE="${{ runner.temp }}/vcpkg/scripts/buildsystems/vcpkg.cmake" + cmake --build "${{ runner.temp }}/consumer-build" --config Release + + - name: Run tests + shell: bash + run: | + ctest --test-dir "${{ runner.temp }}/consumer-build" \ + --build-config Release --output-on-failure + # ============================================================================ # Final gate check # ============================================================================ @@ -456,7 +530,8 @@ jobs: freebsd, netbsd, qemu-crossbuild, windows, - format + format, + vcpkg-integration ] runs-on: ubuntu-24.04 steps: diff --git a/CMakeLists.txt b/CMakeLists.txt index e017d1e7a..a97d1db13 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -292,7 +292,7 @@ endif() # Add header paths. target_include_directories(snmalloc INTERFACE - $ + $ $) if(NOT MSVC) diff --git a/ports/snmalloc/portfile.cmake b/ports/snmalloc/portfile.cmake new file mode 100644 index 000000000..491d9f20b --- /dev/null +++ b/ports/snmalloc/portfile.cmake @@ -0,0 +1,46 @@ +# Without static-shim: INTERFACE only — Release and Debug are identical. +# With static-shim: compiled code is produced — both variants are needed. +if(NOT "static-shim" IN_LIST FEATURES) + set(VCPKG_BUILD_TYPE release) +endif() + +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH + REPO microsoft/snmalloc + REF "v${VERSION}" + SHA512 0 # Placeholder: compute the real SHA512 from the GitHub release tarball before publishing to the vcpkg registry. + HEAD_REF main +) + +# NOTE: The CI overlay port (see .github/workflows/main.yml, vcpkg-integration) +# uses sed to extract from this line onwards to build a portfile that points at +# the local checkout. If you reorder code above this line, update the sed +# pattern there. +vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS + FEATURES + "static-shim" SNMALLOC_STATIC_LIBRARY + INVERTED_FEATURES + "static-shim" SNMALLOC_HEADER_ONLY_LIBRARY +) + +vcpkg_cmake_configure( + SOURCE_PATH "${SOURCE_PATH}" + OPTIONS + -DSNMALLOC_BUILD_TESTING=OFF + ${FEATURE_OPTIONS} +) + +vcpkg_cmake_install() + +vcpkg_cmake_config_fixup( + PACKAGE_NAME snmalloc + CONFIG_PATH share/snmalloc +) + +file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include") +file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/share") + +vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE") + +file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" + DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}") diff --git a/ports/snmalloc/usage b/ports/snmalloc/usage new file mode 100644 index 000000000..a3f875a30 --- /dev/null +++ b/ports/snmalloc/usage @@ -0,0 +1,13 @@ +snmalloc provides CMake integration via: + + find_package(snmalloc CONFIG REQUIRED) + target_link_libraries( PRIVATE snmalloc::snmalloc) + +If installed with the "static-shim" feature, a compiled static library is also +available that replaces malloc/free with a "sn_" prefix (e.g. sn_malloc, sn_free): + + target_link_libraries( PRIVATE snmalloc::snmallocshim-static) + +On non-Windows, the "static-shim" feature also installs shared library shims +(snmalloc::snmallocshim, snmalloc::snmallocshim-checks, snmalloc::snmalloc-minimal) +that can be used for LD_PRELOAD-based allocator replacement. diff --git a/ports/snmalloc/vcpkg.json b/ports/snmalloc/vcpkg.json new file mode 100644 index 000000000..3a5053212 --- /dev/null +++ b/ports/snmalloc/vcpkg.json @@ -0,0 +1,22 @@ +{ + "name": "snmalloc", + "version-semver": "0.7.4", + "description": "A high-performance, message passing based allocator", + "homepage": "https://github.com/microsoft/snmalloc", + "license": "MIT", + "dependencies": [ + { + "name": "vcpkg-cmake", + "host": true + }, + { + "name": "vcpkg-cmake-config", + "host": true + } + ], + "features": { + "static-shim": { + "description": "Build and install snmallocshim-static, a compiled static library that exports malloc/free with a configurable symbol prefix (default: sn_)" + } + } +} \ No newline at end of file diff --git a/src/snmalloc/pal/pal_windows.h b/src/snmalloc/pal/pal_windows.h index a44079dea..4ed643649 100644 --- a/src/snmalloc/pal/pal_windows.h +++ b/src/snmalloc/pal/pal_windows.h @@ -24,6 +24,8 @@ (WINVER >= _WIN32_WINNT_WIN10) && !defined(USE_SYSTEMATIC_TESTING) # define PLATFORM_HAS_VIRTUALALLOC2 # define PLATFORM_HAS_WAITONADDRESS +# pragma comment(lib, "mincore.lib") +# pragma comment(lib, "synchronization.lib") # endif # endif diff --git a/test/vcpkg-consumer/CMakeLists.txt b/test/vcpkg-consumer/CMakeLists.txt new file mode 100644 index 000000000..248b1720a --- /dev/null +++ b/test/vcpkg-consumer/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.16) +project(snmalloc-vcpkg-test CXX) + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set(CMAKE_VERBOSE_MAKEFILE ON) + +enable_testing() + +find_package(snmalloc CONFIG REQUIRED) + +add_executable(test-header-only test_header_only.cpp) +target_link_libraries(test-header-only PRIVATE snmalloc::snmalloc) +add_test(NAME header-only COMMAND test-header-only) + +if(TARGET snmalloc::snmallocshim-static) + add_executable(test-static-shim test_static_shim.cpp) + target_link_libraries(test-static-shim PRIVATE snmalloc::snmallocshim-static) + add_test(NAME static-shim COMMAND test-static-shim) +endif() diff --git a/test/vcpkg-consumer/test_header_only.cpp b/test/vcpkg-consumer/test_header_only.cpp new file mode 100644 index 000000000..75663e609 --- /dev/null +++ b/test/vcpkg-consumer/test_header_only.cpp @@ -0,0 +1,14 @@ +/** + * Minimal vcpkg integration test for the snmalloc header-only target. + * Verifies that find_package(snmalloc) + snmalloc::snmalloc works. + */ +#include + +int main() +{ + void* p = snmalloc::libc::malloc(64); + if (p == nullptr) + return 1; + snmalloc::libc::free(p); + return 0; +} diff --git a/test/vcpkg-consumer/test_static_shim.cpp b/test/vcpkg-consumer/test_static_shim.cpp new file mode 100644 index 000000000..17881983a --- /dev/null +++ b/test/vcpkg-consumer/test_static_shim.cpp @@ -0,0 +1,21 @@ +/** + * Minimal vcpkg integration test for the snmallocshim-static target. + * Verifies that find_package(snmalloc) + snmalloc::snmallocshim-static works. + * The static shim replaces malloc/free with the snmalloc implementation. + */ +#include + +extern "C" +{ + void *sn_malloc(size_t); + void sn_free(void *); +} + +int main() +{ + void* p = sn_malloc(64); + if (p == nullptr) + return 1; + sn_free(p); + return 0; +} diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 000000000..1302ec41a --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,12 @@ +{ + "name": "snmalloc", + "version-semver": "0.7.4", + "description": "A high-performance, message passing based allocator", + "homepage": "https://github.com/microsoft/snmalloc", + "license": "MIT", + "features": { + "static-shim": { + "description": "Build and install snmallocshim-static, a compiled static library that exports malloc/free with a configurable symbol prefix (default: sn_)" + } + } +} \ No newline at end of file