diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..234c924 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,311 @@ +# libnpy — Copilot Agent Instructions + +## What This Project Does + +**libnpy** is a multi-platform C++17 static library for reading and writing NumPy array files: + +- **NPY** — binary format for a single N-dimensional array. The format consists of a fixed magic header, a Python-dict metadata block (dtype, shape, Fortran order), and raw binary data. +- **NPZ** — a PKZIP archive containing one or more NPY files, optionally with DEFLATE compression. + +The library is intended to let C++ projects exchange tensor data with Python deep learning frameworks that consume NumPy files. + +The public CMake target is `npy::npy` (a static library). + +--- + +## Repository Layout + +``` +include/npy/ Public API headers + npy.h Core types, free functions (save/load/peek), NPZ reader/writer classes + tensor.h Default npy::tensor class + +src/ Implementation (compiled into the static library) + npy.cpp NPY header parsing/writing; save/load/peek for NPY files + npz.cpp NPZ reader (npy::npzfilereader) and writer (npy::npzfilewriter) + dtype.cpp dtype string ↔ (data_type_t, endian_t) conversion tables + tensor.cpp npy::tensor non-template helpers + zip.cpp Thin wrapper: npy_deflate / npy_inflate / npy_crc32 + zip.h Internal zip wrapper header + miniz/ Bundled miniz (single-file DEFLATE/inflate + CRC32 library) + +test/ Unit and integration tests (CTest) + libnpy_tests.cpp Test driver / harness + npy_read.cpp NPY read tests + npy_write.cpp NPY write tests + npy_peek.cpp NPY peek (header-only inspection) tests + npz_read.cpp NPZ read tests + npz_write.cpp NPZ write tests + npz_peek.cpp NPZ peek tests + tensor.cpp tensor unit tests + custom_tensor.cpp Tests for user-defined tensor types + crc32.cpp CRC32 correctness tests + exceptions.cpp Error-handling / exception tests + +assets/test/ Golden test fixtures (.npy and .npz files) + +examples/ Standalone example programs + custom_tensors/ Shows how to use the library with a user-defined tensor type + images/ Image-based example + +cmake/ CMake helper files (find-module, install config) +doc/ Doxygen configuration +vcpkg.json vcpkg manifest (consumers who use vcpkg to manage deps) +ports/ + libnpy/ + vcpkg.json Port manifest (metadata, host deps) + portfile.cmake Build/install instructions for vcpkg + usage Usage hint shown after vcpkg install +build/ Out-of-source CMake build directory (not committed) +``` + +--- + +## Key Public Types + +| Type | Header | Purpose | +|------|--------|---------| +| `npy::tensor` | `tensor.h` | Default N-dimensional array. Supports row-major and Fortran (column-major) layout. | +| `npy::data_type_t` | `npy.h` | Enum of all supported element types: INT8/UINT8 … INT64/UINT64, FLOAT32/FLOAT64, COMPLEX64/COMPLEX128, BOOL, UNICODE_STRING. | +| `npy::endian_t` | `npy.h` | NATIVE / BIG / LITTLE. | +| `npy::boolean` | `npy.h` | Byte-sized bool wrapper (avoids `std::vector` bitfield issues). | +| `npy::header_info` | `npy.h` | Parsed NPY header: dtype, endianness, fortran_order, shape, max_element_length. | +| `npy::npzfilewriter` | `npy.h` | Streams NPY entries into a new NPZ file. | +| `npy::npzfilereader` | `npy.h` | Reads and inspects entries from an existing NPZ file. | + +--- + +## Core API + +```cpp +// NPY — single-array files +npy::header_info npy::peek(const std::string &path); +template class Tensor> +Tensor npy::load(const std::string &path); +template +void npy::save(const std::string &path, const Tensor &tensor, + npy::endian_t endian = npy::endian_t::NATIVE); + +// NPZ — multi-array archives +npy::npzfilereader reader("file.npz"); +bool reader.contains("name.npy"); +npy::header_info reader.peek("name.npy"); +Tensor reader.read("name.npy"); + +npy::npzfilewriter writer("file.npz"); +writer.write("name.npy", tensor); // no compression +writer.write("name.npy", tensor, true); // with DEFLATE compression +``` + +--- + +## Custom Tensor Support + +The library is not tied to `npy::tensor`. Any class that exposes these five members will work transparently with all save/load/write/read overloads: + +| Member | Signature | Semantics | +|--------|-----------|-----------| +| `data()` | `const T* data() const` | Pointer to contiguous element buffer | +| `shape()` | `const std::vector& shape() const` | Size of each dimension | +| `size()` | `size_t size() const` | Total number of elements | +| `dtype()` | `npy::data_type_t dtype() const` | Element type tag | +| `fortran_order()` | `bool fortran_order() const` | Column-major flag | + +See `examples/custom_tensors/` and `test/custom_tensor.cpp` for worked examples. + +--- + +## How It Works + +### NPY read path (`src/npy.cpp`) +1. Open file stream, read the 10-byte static header (magic `\x93NUMPY`, version bytes, header length). +2. Parse the Python-dict metadata string into a `header_info` (dtype string → `data_type_t` + `endian_t` via `dtype.cpp`, shape tuple, fortran_order flag). +3. Read the raw binary payload directly into the tensor's data buffer. +4. If the file endianness differs from the machine's native endianness, byte-swap each element. + +### NPY write path +1. Build the Python-dict header string from shape, dtype string (via `npy::to_dtype`), and fortran_order. +2. Pad the header to a multiple of 64 bytes for alignment. +3. Write magic + version + header length field + padded header + raw binary data. + +### NPZ read/write path (`src/npz.cpp` + `src/zip.cpp`) +- Uses the PKZIP local-file / central-directory structure directly (no external zlib dependency at link time — miniz is bundled). +- **Writing**: each `npzfilewriter::write` call serialises the NPY bytes into memory, optionally deflates them with `npy_deflate`, appends a local-file record, then on destruction writes the central directory and end-of-central-directory record. +- **Reading**: `npzfilereader` scans the central directory to build a name→offset index, then seeks to each local-file record on demand; compressed entries are inflated with `npy_inflate` before NPY parsing. +- CRC32 checksums are computed (via `npy_crc32` → miniz) and validated on read. + +### dtype mapping (`src/dtype.cpp`) +Maintains two static lookup tables: +- `data_type_t` + `endian_t` → NPY dtype string (e.g. `"` on GitHub. +2. Compute the SHA512 of the archive: `vcpkg hash `. +3. Replace the placeholder `SHA512 0` in `ports/libnpy/portfile.cmake` with the real hash. +4. Run `vcpkg install libnpy --overlay-ports=ports` to verify. +5. Run `vcpkg x-add-version libnpy --overlay-ports=ports` to register the version. + +--- + +## Coding Conventions + +- **Standard**: C++17 throughout. +- **Namespace**: all public symbols live in `npy::`. +- **Headers**: public API is in `include/npy/`; internal helpers (e.g. `zip.h`) stay in `src/`. +- **Formatting**: clang-format is enforced via the `libnpy_format` CMake target (uses clang-format-10/14/18 if found). +- **Error handling**: invalid files or unsupported configurations throw `std::runtime_error` (or derived types). See `test/exceptions.cpp`. +- **No external runtime dependencies**: miniz is vendored in `src/miniz/` so the built library has no link-time dependencies beyond the C++ standard library. + +--- + +## Development Workflow and Deployment Process + +### Core Principles + +When working on this codebase, follow these fundamental principles: + +#### 1. Move Slow to Go Fast +Make small, incremental changes that can be tested and understood in isolation. Breaking work into smaller pieces makes debugging easier and reduces the risk of introducing new issues. Don't try to fix everything at once—focus on one problem at a time. + +#### 2. Fix Root Causes, Don't Patch Symptoms +When something goes wrong, investigate deeply to find the underlying issue rather than just addressing surface-level problems. Ask "why" multiple times to get to the real cause. A quick fix that doesn't address the root cause will lead to more problems later. + +#### 3. Make a Plan and Get Approval First +Before making any changes to the codebase: +- Create a detailed plan describing the changes you intend to make +- Document the reasoning behind each change +- Save the plan to a file (e.g., `/memories/session/work-plan.md`) for tracking and reference +- Present the plan to the maintainer for approval +- Only proceed with implementation after explicit approval + +#### 4. Establish a Baseline +Before beginning work: +- Run the full test suite and document the results in your plan file +- Record which tests pass and which fail (if any) +- Note the current state of the build system +- This prevents confusion about whether an error is pre-existing or newly introduced +- Always compare results against the baseline after making changes + +#### 5. All Changes Need Review +Every change must go through a review process before being considered complete. See the review workflow below. + +#### 6. You Don't Commit Code +As an AI agent, you prepare and test changes but never commit them to version control. The maintainer reviews and commits all changes. Focus on producing high-quality, well-tested code ready for human review. + +--- + +### Review Process + +All changes must follow this iterative review workflow: + +#### Step 1: Initial Implementation +Complete your planned changes according to the approved plan. + +#### Step 2: Spawn Review Subagent +- Invoke a subagent with a **fresh context** to review your changes +- Provide the subagent with: + - The original requirements/plan + - The changes made (diffs, file locations) + - Any relevant context about the codebase +- The subagent should evaluate: + - Correctness and completeness + - Adherence to coding conventions + - Potential edge cases or bugs + - Test coverage + - Documentation quality + +#### Step 3: Address Review Comments +- Document all comments and suggestions from the review subagent +- Create a new plan addressing each comment +- Present this remediation plan to the maintainer for approval +- Only proceed after approval + +#### Step 4: Implement Fixes +Make the changes to address review comments. + +#### Step 5: Iterate +Return to Step 2 and repeat the review cycle until the subagent reviewer has no further suggestions or concerns. + +#### Trivial Changes Exception +Simple changes may bypass the full review process, but **you do not decide what is trivial**. If you believe a change is trivial (e.g., fixing a typo, updating a comment), explicitly propose this to the maintainer and await confirmation. Examples that might qualify: +- Fixing obvious typos in comments or documentation +- Updating copyright years +- Correcting a broken external link + +When in doubt, use the full review process. + +--- + +### Workflow Summary + +A typical development session follows this pattern: + +1. **Understand the Request**: Gather context about what needs to be done +2. **Establish Baseline**: Run tests and document current state +3. **Create Plan**: Document proposed changes and get approval +4. **Implement**: Make the approved changes incrementally +5. **Review Loop**: Use subagent reviews iteratively until code is clean +6. **Final Handoff**: Present completed, reviewed changes to maintainer for commit + +This process ensures quality, maintainability, and clear communication throughout the development lifecycle. diff --git a/.github/skills/version-bump/SKILL.md b/.github/skills/version-bump/SKILL.md new file mode 100644 index 0000000..3a2183d --- /dev/null +++ b/.github/skills/version-bump/SKILL.md @@ -0,0 +1,84 @@ +--- +name: version-bump +description: "Bump the libnpy library version for release. Use when: updating the version number, preparing a release, changing the version to a specific value, writing a CHANGELOG entry from recent commits." +argument-hint: "Target version, e.g. 2.2.0" +--- + +# Version Bump + +Bump the libnpy version across all files and generate a CHANGELOG entry from recent commits. + +## When to Use + +- The maintainer asks to bump / change / update the version (e.g. "Bump the version to 2.2.0") +- Preparing a new release of the library + +## Procedure + +### 1. Parse the requested version + +Extract the target version string (`MAJOR.MINOR.PATCH`) from the user's request. +Read the current version from the `VERSION` file in the repository root. +Abort if the requested version equals the current version. + +### 2. Update every version location + +Apply the new version to **all** of the following files. No other files contain the version. + +| File | What to change | +|------|---------------| +| `VERSION` | Replace the entire file content with the new version string (no trailing newline beyond what exists). | +| `vcpkg.json` (repo root) | Update the `"version"` field value. | +| `ports/libnpy/vcpkg.json` | Update the `"version"` field value. | +| `include/npy/npy.h` | Update **all four** preprocessor defines: `NPY_VERSION_MAJOR`, `NPY_VERSION_MINOR`, `NPY_VERSION_PATCH`, and `NPY_VERSION_STRING`. | + +Do **not** touch `CMakeLists.txt` — it reads the version dynamically from the `VERSION` file. + +### 3. Generate the CHANGELOG entry + +Run `git log` to collect commits on the current branch since the latest release tag. +Use a command like: + +```bash +git log --oneline --no-decorate $(git describe --tags --abbrev=0)..HEAD +``` + +If no tags exist, fall back to: + +```bash +git log --oneline --no-decorate -20 +``` + +Compose a new entry and **prepend** it to `CHANGELOG.md` immediately after the `# Changelog` heading, using this exact format: + +```markdown +## [YYYY-MM-DD - Version X.Y.Z](https://github.com/matajoh/libnpy/releases/tag/vX.Y.Z) + +One-sentence summary of the release theme. + +Improvements: +- Item 1 +- Item 2 + +Bugfixes: +- Item 1 +``` + +Rules for the entry: +- Use today's date in `YYYY-MM-DD` format. +- Categorise changes under **Improvements** and/or **Bugfixes** (omit a category if empty). +- Write entries in simple past tense, concise, one line each. +- Do not include merge commits, version-bump commits, or trivial CI-only changes unless they are user-facing. +- Match the tone and style of the existing entries in `CHANGELOG.md`. + +### 4. Update RELEASE_NOTES + +Replace the entire content of the `RELEASE_NOTES` file with the body of the new changelog entry (everything after the `## [...]` heading line). This file is plain text with no markdown heading. + +### 5. Verify + +After all edits, run a search for the **old** version string across the repository to confirm no stale references remain. Report the result to the maintainer. + +### 6. Present changes for review + +List every file modified and summarise the changes so the maintainer can review before committing. diff --git a/.github/workflows/prgate.yaml b/.github/workflows/prgate.yaml index f45d28f..70c0183 100644 --- a/.github/workflows/prgate.yaml +++ b/.github/workflows/prgate.yaml @@ -354,4 +354,85 @@ jobs: - name: CMake test working-directory: ${{github.workspace}}/examples/custom_tensors/build - run: ctest -V --build-config Release --timeout 120 --output-on-failure -T Test -L npy \ No newline at end of file + run: ctest -V --build-config Release --timeout 120 --output-on-failure -T Test -L npy + + linux-vcpkg: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Bootstrap vcpkg + run: | + git clone https://github.com/microsoft/vcpkg.git $HOME/vcpkg + bash $HOME/vcpkg/bootstrap-vcpkg.sh + + - name: CMake config + run: | + cmake -B ${{github.workspace}}/build-vcpkg-test \ + -S ${{github.workspace}}/test/vcpkg \ + -DCMAKE_TOOLCHAIN_FILE=$HOME/vcpkg/scripts/buildsystems/vcpkg.cmake \ + -DVCPKG_OVERLAY_PORTS=${{github.workspace}}/test/vcpkg/port + + - name: CMake build + run: cmake --build ${{github.workspace}}/build-vcpkg-test --config Release + + - name: CMake test + working-directory: ${{github.workspace}}/build-vcpkg-test + run: ctest -V --build-config Release --timeout 120 --output-on-failure + + windows-vcpkg: + runs-on: windows-latest + defaults: + run: + shell: pwsh + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Bootstrap vcpkg + run: | + git clone https://github.com/microsoft/vcpkg.git "$env:USERPROFILE\vcpkg" + & "$env:USERPROFILE\vcpkg\bootstrap-vcpkg.bat" + + - name: CMake config + run: | + cmake -B "${{github.workspace}}\build-vcpkg-test" ` + -S "${{github.workspace}}\test\vcpkg" ` + -DCMAKE_TOOLCHAIN_FILE="$env:USERPROFILE\vcpkg\scripts\buildsystems\vcpkg.cmake" ` + -DVCPKG_OVERLAY_PORTS="${{github.workspace}}\test\vcpkg\port" + + - name: CMake build + run: cmake --build ${{github.workspace}}\build-vcpkg-test --config Release + + - name: CMake test + working-directory: ${{github.workspace}}\build-vcpkg-test + run: ctest -V --build-config Release --timeout 120 --output-on-failure + + macos-vcpkg: + runs-on: macos-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Bootstrap vcpkg + run: | + git clone https://github.com/microsoft/vcpkg.git $HOME/vcpkg + bash $HOME/vcpkg/bootstrap-vcpkg.sh + + - name: CMake config + run: | + cmake -B ${{github.workspace}}/build-vcpkg-test \ + -S ${{github.workspace}}/test/vcpkg \ + -DCMAKE_TOOLCHAIN_FILE=$HOME/vcpkg/scripts/buildsystems/vcpkg.cmake \ + -DVCPKG_OVERLAY_PORTS=${{github.workspace}}/test/vcpkg/port + + - name: CMake build + run: cmake --build ${{github.workspace}}/build-vcpkg-test --config Release + + - name: CMake test + working-directory: ${{github.workspace}}/build-vcpkg-test + run: ctest -V --build-config Release --timeout 120 --output-on-failure diff --git a/CHANGELOG.md b/CHANGELOG.md index 33817af..d99d66e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2026-03-12 - Version 2.1.1](https://github.com/matajoh/libnpy/releases/tag/v2.1.1) + +Patch release adding vcpkg packaging support. + +Improvements: +- Added vcpkg port files and removed remnants of the old NuGet packaging approach + ## [2026-02-11 - Version 2.1.0](https://github.com/matajoh/libnpy/releases/tag/v2.1.0) Minor version adding support for boolean tensors. diff --git a/CMakeLists.txt b/CMakeLists.txt index b7fd3aa..079a7f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,7 +68,7 @@ endif() target_include_directories(npy PUBLIC - $ + $ $ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src @@ -84,18 +84,19 @@ endif() # -------------------- INSTALL ------------------------------------ -set(INSTALL_CONFIGDIR cmake) -set(INSTALL_LIBDIR lib) -set(INSTALL_INCLUDEDIR include) -set(LIBNPY_INSTALL_TARGETS npy) +include(GNUInstallDirs) -install(TARGETS ${LIBNPY_INSTALL_TARGETS} +install(TARGETS npy EXPORT ${PROJECT_NAME}_Targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} +) + # Create a ConfigVersion.cmake file include(CMakePackageConfigHelpers) write_basic_package_version_file( @@ -106,29 +107,18 @@ write_basic_package_version_file( configure_package_config_file(${PROJECT_SOURCE_DIR}/cmake/${PROJECT_NAME}Config.cmake.in ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake - INSTALL_DESTINATION - ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}/cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME} ) install(EXPORT ${PROJECT_NAME}_Targets FILE ${PROJECT_NAME}Targets.cmake NAMESPACE ${PROJECT_NAME}:: - DESTINATION ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}/cmake) + DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}) -install(FILES ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake +install(FILES + ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake ${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake - DESTINATION ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}/cmake) - -export(EXPORT ${PROJECT_NAME}_Targets - FILE ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake - NAMESPACE ${PROJECT_NAME}::) - -export(PACKAGE ${PROJECT_NAME}) - -install(DIRECTORY include/ DESTINATION ${INSTALL_INCLUDEDIR}) -install(FILES - DESTINATION ${INSTALL_INCLUDEDIR}/npy -) + DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}) # -------------------- Package ------------------------------------ diff --git a/README.md b/README.md index 933b125..fa7de13 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # libnpy `libnpy` is a multi-platform C++ library for reading and writing NPY and -NPZ files, with an additional .NET interface. It was built with the +NPZ files. It was built with the intention of making it easier for multi-language projects to use NPZ and NPY files for data storage, given their simplicity and support across most Python deep learning frameworks. diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 1c8b71e..cca340c 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -1,10 +1,4 @@ -Improvements: -- Increased CHUNK size as per miniz instructions -- Added tests for very large arrays in NPZ files -- Added some CI tests to catch issues across platforms -- Removed the internal IO streams in favor of just using stringstream -- NPZs can now be read from and written to memory +Patch release adding vcpkg packaging support. -Bugfixes: -- Fixed an issue where very large arrays in NPZ files would throw an error -- Fixed a bug with mac builds due to deprecated APIs +Improvements: +- Added vcpkg port files and removed remnants of the old NuGet packaging approach diff --git a/VERSION b/VERSION index 50aea0e..7c32728 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1.0 \ No newline at end of file +2.1.1 \ No newline at end of file diff --git a/include/npy/npy.h b/include/npy/npy.h index 1ca72b4..ac9b1bd 100644 --- a/include/npy/npy.h +++ b/include/npy/npy.h @@ -31,8 +31,8 @@ #define NPY_VERSION_MAJOR 2 #define NPY_VERSION_MINOR 1 -#define NPY_VERSION_PATCH 0 -#define NPY_VERSION_STRING "2.1.0" +#define NPY_VERSION_PATCH 1 +#define NPY_VERSION_STRING "2.1.1" const int STATIC_HEADER_LENGTH = 10; diff --git a/nuget/template.nuspec.in b/nuget/template.nuspec.in deleted file mode 100644 index 488660d..0000000 --- a/nuget/template.nuspec.in +++ /dev/null @@ -1,19 +0,0 @@ - - - - @LIBNPY_NUGET_NAME@ - @LIBNPY_VERSION@ - @LIBNPY_NUGET_NAME@ - Matthew Johnson - Matthew Johnson - false - MIT - https://github.com/matajoh/libnpy - C++ library for reading and writing NPY and NPZ files. - @LIBNPY_RELEASE_NOTES@ - native - - - - - \ No newline at end of file diff --git a/nuget/template.targets.in b/nuget/template.targets.in deleted file mode 100644 index 09092a7..0000000 --- a/nuget/template.targets.in +++ /dev/null @@ -1,15 +0,0 @@ - - - - $(MSBuildThisFileDirectory)include;%(AdditionalIncludeDirectories) - - - $(MSBuildThisFileDirectory)lib\;%(AdditionalLibraryDirectories) - @LIBNPY_NUGET_LIB@;%(AdditionalDependencies) - - - - - - - \ No newline at end of file diff --git a/ports/libnpy/portfile.cmake b/ports/libnpy/portfile.cmake new file mode 100644 index 0000000..3d14424 --- /dev/null +++ b/ports/libnpy/portfile.cmake @@ -0,0 +1,25 @@ +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH + REPO matajoh/libnpy + REF "v${VERSION}" + SHA512 0 # TODO: replace with the actual SHA512 of the release archive once the tag is published + HEAD_REF main +) + +vcpkg_check_linkage(ONLY_STATIC_LIBRARY) + +vcpkg_cmake_configure( + SOURCE_PATH "${SOURCE_PATH}" + OPTIONS + -DLIBNPY_BUILD_TESTS=OFF + -DLIBNPY_BUILD_DOCUMENTATION=OFF +) + +vcpkg_cmake_install() + +vcpkg_cmake_config_fixup(PACKAGE_NAME npy) + +file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include") +file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/share") + +vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE") diff --git a/ports/libnpy/usage b/ports/libnpy/usage new file mode 100644 index 0000000..3384898 --- /dev/null +++ b/ports/libnpy/usage @@ -0,0 +1,4 @@ +The package libnpy provides CMake targets: + + find_package(npy CONFIG REQUIRED) + target_link_libraries(main PRIVATE npy::npy) diff --git a/ports/libnpy/vcpkg.json b/ports/libnpy/vcpkg.json new file mode 100644 index 0000000..7b1edce --- /dev/null +++ b/ports/libnpy/vcpkg.json @@ -0,0 +1,17 @@ +{ + "name": "libnpy", + "version": "2.1.1", + "description": "A C++17 library for reading and writing NumPy NPY and NPZ array files", + "homepage": "https://github.com/matajoh/libnpy", + "license": "MIT", + "dependencies": [ + { + "name": "vcpkg-cmake", + "host": true + }, + { + "name": "vcpkg-cmake-config", + "host": true + } + ] +} \ No newline at end of file diff --git a/test/vcpkg/CMakeLists.txt b/test/vcpkg/CMakeLists.txt new file mode 100644 index 0000000..db928e2 --- /dev/null +++ b/test/vcpkg/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.15) + +project(vcpkg_test VERSION 0.0.1 LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) + +find_package(npy CONFIG REQUIRED) + +add_executable(vcpkg_test main.cpp) +target_link_libraries(vcpkg_test PRIVATE npy::npy) + +enable_testing() +add_test(NAME vcpkg_test COMMAND vcpkg_test) diff --git a/test/vcpkg/main.cpp b/test/vcpkg/main.cpp new file mode 100644 index 0000000..d1d14ab --- /dev/null +++ b/test/vcpkg/main.cpp @@ -0,0 +1,40 @@ +#include +#include +#include +#include + +int main() { + const std::string path = "vcpkg_test.npy"; + + // Create a small 2x3 tensor of float32 + npy::tensor original({2, 3}); + for (size_t i = 0; i < original.size(); ++i) { + original.data()[i] = static_cast(i) * 1.5f; + } + + // Save to disk + npy::save(path, original); + + // Load back + auto loaded = npy::load(path); + + // Verify shape + if (loaded.shape() != original.shape()) { + std::cerr << "Shape mismatch" << std::endl; + std::filesystem::remove(path); + return EXIT_FAILURE; + } + + // Verify data + for (size_t i = 0; i < original.size(); ++i) { + if (loaded.data()[i] != original.data()[i]) { + std::cerr << "Data mismatch at index " << i << std::endl; + std::filesystem::remove(path); + return EXIT_FAILURE; + } + } + + std::filesystem::remove(path); + std::cout << "vcpkg integration test passed" << std::endl; + return EXIT_SUCCESS; +} diff --git a/test/vcpkg/port/libnpy/portfile.cmake b/test/vcpkg/port/libnpy/portfile.cmake new file mode 100644 index 0000000..2ad2ba5 --- /dev/null +++ b/test/vcpkg/port/libnpy/portfile.cmake @@ -0,0 +1,17 @@ +vcpkg_check_linkage(ONLY_STATIC_LIBRARY) + +vcpkg_cmake_configure( + SOURCE_PATH "${CURRENT_PORT_DIR}/../../../../" + OPTIONS + -DLIBNPY_BUILD_TESTS=OFF + -DLIBNPY_BUILD_DOCUMENTATION=OFF +) + +vcpkg_cmake_install() + +vcpkg_cmake_config_fixup(PACKAGE_NAME npy) + +file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include") +file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/share") + +vcpkg_install_copyright(FILE_LIST "${CURRENT_PORT_DIR}/../../../../LICENSE") diff --git a/test/vcpkg/port/libnpy/vcpkg.json b/test/vcpkg/port/libnpy/vcpkg.json new file mode 100644 index 0000000..7b1edce --- /dev/null +++ b/test/vcpkg/port/libnpy/vcpkg.json @@ -0,0 +1,17 @@ +{ + "name": "libnpy", + "version": "2.1.1", + "description": "A C++17 library for reading and writing NumPy NPY and NPZ array files", + "homepage": "https://github.com/matajoh/libnpy", + "license": "MIT", + "dependencies": [ + { + "name": "vcpkg-cmake", + "host": true + }, + { + "name": "vcpkg-cmake-config", + "host": true + } + ] +} \ No newline at end of file diff --git a/test/vcpkg/vcpkg.json b/test/vcpkg/vcpkg.json new file mode 100644 index 0000000..3a5348e --- /dev/null +++ b/test/vcpkg/vcpkg.json @@ -0,0 +1,7 @@ +{ + "name": "vcpkg-test", + "version": "0.0.1", + "dependencies": [ + "libnpy" + ] +} \ No newline at end of file diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 0000000..5ae29cb --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,7 @@ +{ + "name": "libnpy", + "version": "2.1.1", + "description": "A C++17 library for reading and writing NumPy NPY and NPZ array files", + "homepage": "https://github.com/matajoh/libnpy", + "license": "MIT" +} \ No newline at end of file