Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
74e3e1e
feat(vips): a libvips loader's skeleton, registered by the program (S…
ShadobaDev Oct 24, 2026
3fc9ab3
feat(vips): the composite decoded in bands of rows (S7.3, 2)
ShadobaDev Oct 24, 2026
b2c678d
feat(vips): layers, ZIP and indexed in psdload (S7.3, 3)
ShadobaDev Oct 24, 2026
9778b38
feat(vips): psdsave, an image as a one-layer PSD (S7.4)
ShadobaDev Oct 24, 2026
be4313d
fix(writer): name the composite's transparency where the count cannot
ShadobaDev Oct 24, 2026
b542d08
docs(vips): the plugin documented; CMYK as libvips holds it (S7.2-S7.…
ShadobaDev Oct 24, 2026
fcd12d6
refactor(vips): one file pair a side, everything named minipsd_vips_*
ShadobaDev Oct 24, 2026
9a8697b
chore(release): 0.3.2
ShadobaDev Oct 25, 2026
8d759b2
feat(writer): a composite and layers without transparency
ShadobaDev Oct 25, 2026
cfc3161
perf(vips): psdsave encodes every channel once
ShadobaDev Oct 25, 2026
1f95c25
feat(compression): a layer's own compression; psdsave's compression o…
ShadobaDev Oct 25, 2026
5e8f432
fix(channels): bound a channel's sides when reading; refuse an RLE ro…
ShadobaDev Oct 25, 2026
4907dd0
perf(vips): psdsave reads the image once, in bands; ZIP with prediction
ShadobaDev Oct 25, 2026
47a9a62
build(release): the libvips plugin as minipsd-vips-X.Y.Z.zip
ShadobaDev Oct 25, 2026
7995af7
docs(misc): 0.4.0
ShadobaDev Oct 25, 2026
185f05d
refactor(vips): laid out and named as libvips' foreign/
ShadobaDev Oct 25, 2026
e96832b
feat(vips): psdsave_layers, a layered document saved through libvips
ShadobaDev Oct 25, 2026
e8326f9
feat(vips): masks and groups through psdload and psdsave_layers
ShadobaDev Oct 25, 2026
5a0abbc
refactor(vips): the plugin's own names, not libvips'
ShadobaDev Oct 25, 2026
e64c33a
build(vips): the released zip carries its SBOM fragment
ShadobaDev Oct 25, 2026
c08f35e
docs(vips): what the plugin does, psdsave_layers, 0.4.0
ShadobaDev Oct 25, 2026
00aaeeb
test(writer): a mask wider than the canvas sizes minipsd_write's pieces
ShadobaDev Oct 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 25 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ jobs:
matrix:
include:
# windows-2022, not windows-latest: the msvc preset's generator is "Visual Studio 17 2022".
# msvc also builds and runs examples/vips_composite.c on libvips' prebuilt Windows build
# (fetched, pinned; MSVC is what Platemaker builds with).
- { os: windows-2022, preset: msvc, vips_example: ON }
# msvc also builds and runs examples/vips_composite.c and the libvips plugin
# (libvips-plugin/) on libvips' prebuilt Windows build (fetched, pinned; MSVC is what
# Platemaker builds with).
- { os: windows-2022, preset: msvc, vips: ON }
- { os: windows-latest, preset: mingw }
# linux-gcc also reads psd-tools' 315 files (22 MB, pinned by hash): every comparison
# with psd-tools, Photoshop's ZIP files through zlib among them.
Expand Down Expand Up @@ -77,10 +78,30 @@ jobs:
- name: Configure, build, test
if: matrix.preset != 'mingw'
run: |
cmake --preset ${{ matrix.preset }} -DMINIPSD_REQUIRE_PSD_TOOLS=ON -DMINIPSD_PSD_TOOLS_FILES=${{ matrix.psd_tools_files || 'OFF' }} -DMINIPSD_VIPS_EXAMPLE=${{ matrix.vips_example || 'OFF' }} "-DPython3_EXECUTABLE=${{ steps.python.outputs.python-path }}"
cmake --preset ${{ matrix.preset }} -DMINIPSD_REQUIRE_PSD_TOOLS=ON -DMINIPSD_PSD_TOOLS_FILES=${{ matrix.psd_tools_files || 'OFF' }} -DMINIPSD_VIPS_EXAMPLE=${{ matrix.vips || 'OFF' }} -DMINIPSD_VIPS_PLUGIN=${{ matrix.vips || 'OFF' }} "-DPython3_EXECUTABLE=${{ steps.python.outputs.python-path }}"
cmake --build --preset ${{ matrix.preset }}
ctest --preset ${{ matrix.preset }}

# The plugin as released (minipsd-vips-X.Y.Z.zip, tools/package_vips.cmake): built from the
# zip alone, outside the repository, its example run, its SBOM fragment checked against its
# files; libvips as fetched above. The release builds it again on Linux before publishing.
- name: Check the released plugin builds and runs
if: matrix.vips == 'ON'
shell: pwsh
run: |
$PSNativeCommandUseErrorActionPreference = $true
cmake -DOUTPUT_DIR="$env:RUNNER_TEMP/dist" -P tools/package_vips.cmake
$zip = Get-Item "$env:RUNNER_TEMP/dist/minipsd-vips-*.zip"
cmake -E chdir "$env:RUNNER_TEMP" cmake -E tar xf $zip.FullName
$unpacked = Join-Path $env:RUNNER_TEMP $zip.BaseName
cmake "-DSPDX=$unpacked/minipsd-vips.spdx.json" "-DBASE=$unpacked" -DCOMPLETE=ON -P tools/check_spdx.cmake
$deps = "$env:GITHUB_WORKSPACE/build/${{ matrix.preset }}/_deps"
cmake -S (Join-Path $env:RUNNER_TEMP $zip.BaseName) -B "$env:RUNNER_TEMP/plugin" `
"-DFETCHCONTENT_SOURCE_DIR_MINIPSD_LIBVIPS=$deps/minipsd_libvips-src" `
"-DFETCHCONTENT_SOURCE_DIR_MINIPSD_ZLIB_HEADERS=$deps/minipsd_zlib_headers-src"
cmake --build "$env:RUNNER_TEMP/plugin"
ctest --test-dir "$env:RUNNER_TEMP/plugin" -C Debug --output-on-failure

# The same tests, instrumented, on Linux:
# linux-asan AddressSanitizer + UBSan: out-of-bounds access, overflow, undefined shifts.
# No round trip: Python would need the sanitizer runtime preloaded.
Expand Down
30 changes: 27 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Release: a pushed tag X.Y.Z (bare semver) checks that CI already passed on its commit on master,
# checks the tag against the header version and the changelog, and publishes minipsd.h (include/ joined into one file by
# tools/amalgamate.cmake) + minipsd.h.sha256 as a GitHub Release with a build-provenance attestation. "Run workflow" (workflow_dispatch) does everything except publish,
# tools/amalgamate.cmake) + minipsd.h.sha256, and the libvips plugin as a CMake project that builds as it is
# (minipsd-vips-X.Y.Z.zip, tools/package_vips.cmake, built and run here first) + its .sha256, as a GitHub Release
# with build-provenance attestations. "Run workflow" (workflow_dispatch) does everything except publish,
# so it is a dry run. See docs/GITHUB-RELEASE.md.
name: Release

Expand Down Expand Up @@ -63,10 +65,30 @@ jobs:
cmake -DOUTPUT=dist/minipsd.h -P tools/amalgamate.cmake
cd dist && sha256sum minipsd.h > minipsd.h.sha256 && cat minipsd.h.sha256

# Verifiable with: gh attestation verify minipsd.h --repo ShadobaDev/minipsd
# The plugin's sources, the single-file header, how libvips is found and an example, one zip.
- name: Stage the libvips plugin and its checksum
run: |
cmake -DOUTPUT_DIR=dist -P tools/package_vips.cmake
cd dist && for zip in minipsd-vips-*.zip; do sha256sum "$zip" > "$zip.sha256" && cat "$zip.sha256"; done

# Built from the zip alone, outside the repository, against the system's libvips; its example
# saves a PSD through the plugin and reads it back. Its SBOM fragment checked against its files.
- name: Check the plugin builds and runs as released
run: |
sudo apt-get update && sudo apt-get install -y --no-install-recommends libvips-dev ninja-build
mkdir "$RUNNER_TEMP/plugin" && cd "$RUNNER_TEMP/plugin"
cmake -E tar xf "$GITHUB_WORKSPACE"/dist/minipsd-vips-*.zip
cmake -DSPDX="$(echo minipsd-vips-*)/minipsd-vips.spdx.json" -DBASE="$(echo minipsd-vips-*)" -DCOMPLETE=ON -P "$GITHUB_WORKSPACE"/tools/check_spdx.cmake
cmake -S minipsd-vips-* -B build -G Ninja
cmake --build build
ctest --test-dir build --output-on-failure

# Verifiable with: gh attestation verify minipsd.h --repo ShadobaDev/minipsd (the zip alike)
- uses: actions/attest-build-provenance@v4
with:
subject-path: dist/minipsd.h
subject-path: |
dist/minipsd.h
dist/minipsd-vips-*.zip

- name: Publish the GitHub Release
if: github.ref_type == 'tag'
Expand All @@ -78,3 +100,5 @@ jobs:
files: |
dist/minipsd.h
dist/minipsd.h.sha256
dist/minipsd-vips-*.zip
dist/minipsd-vips-*.zip.sha256
56 changes: 12 additions & 44 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ project(minipsd
# Tests and install rules are for working on minipsd itself, not for consumers.
option(MINIPSD_BUILD_TESTS "Build the minipsd tests" ${PROJECT_IS_TOP_LEVEL})
option(MINIPSD_INSTALL "Generate the minipsd install rules" ${PROJECT_IS_TOP_LEVEL})
# The libvips plugin (libvips-plugin/): psdload and psdsave for a program that links libvips.
option(MINIPSD_VIPS_PLUGIN "Build the libvips plugin, minipsd::vips (libvips fetched on Windows)" OFF)

if(PROJECT_IS_TOP_LEVEL OR MINIPSD_BUILD_TESTS)
if(PROJECT_IS_TOP_LEVEL OR MINIPSD_BUILD_TESTS OR MINIPSD_VIPS_PLUGIN)
enable_language(C) # also gives GNUInstallDirs a known architecture
endif()
include(GNUInstallDirs)
Expand All @@ -50,55 +52,18 @@ target_include_directories(minipsd INTERFACE
# add_subdirectory, FetchContent and find_package (a variable would not survive
# FetchContent_MakeAvailable's function scope). Its timestamp honours SOURCE_DATE_EPOCH.
# ---------------------------------------------------------------------------
# Every header is listed with its checksums; SPDX requires SHA-1 per file and derives the package
# verification code from those (sorted, concatenated, hashed again).
file(GLOB_RECURSE _minipsd_headers RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/include"
CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h")
list(SORT _minipsd_headers)
# Absolute paths: relative ones would be taken from the source root, where no header is, and an
# edited header would refresh neither the checksums here nor tests/'s single-file header.
list(TRANSFORM _minipsd_headers PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/include/" OUTPUT_VARIABLE _minipsd_header_paths)
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${_minipsd_header_paths}")
set(_minipsd_sbom_file [=[

{
"SPDXID": "SPDXRef-File-@_minipsd_id@",
"fileName": "./include/@_minipsd_rel@",
"checksums": [
{ "algorithm": "SHA1", "checksumValue": "@_minipsd_sha1@" },
{ "algorithm": "SHA256", "checksumValue": "@_minipsd_sha256@" }
],
"licenseConcluded": "MIT",
"licenseInfoInFiles": [ "MIT" ],
"copyrightText": "Copyright (c) 2026 Bartlomiej Mucha <shadobadev@gmail.com>"
}]=])
set(_minipsd_sbom_contains [=[

{
"spdxElementId": "SPDXRef-Package-minipsd",
"relationshipType": "CONTAINS",
"relatedSpdxElement": "SPDXRef-File-@_minipsd_id@"
}]=])
set(_minipsd_files "")
set(_minipsd_contains "")
set(_minipsd_sha1s "")
foreach(_minipsd_rel IN LISTS _minipsd_headers)
string(REGEX REPLACE "[^A-Za-z0-9.-]" "-" _minipsd_id "${_minipsd_rel}")
file(SHA1 "${CMAKE_CURRENT_SOURCE_DIR}/include/${_minipsd_rel}" _minipsd_sha1)
file(SHA256 "${CMAKE_CURRENT_SOURCE_DIR}/include/${_minipsd_rel}" _minipsd_sha256)
list(APPEND _minipsd_sha1s "${_minipsd_sha1}")
string(CONFIGURE "${_minipsd_sbom_file}" _minipsd_entry @ONLY)
list(APPEND _minipsd_files "${_minipsd_entry}")
string(CONFIGURE "${_minipsd_sbom_contains}" _minipsd_entry @ONLY)
list(APPEND _minipsd_contains "${_minipsd_entry}")
endforeach()
list(JOIN _minipsd_files "," MINIPSD_SBOM_FILES)
list(JOIN _minipsd_contains "," MINIPSD_SBOM_CONTAINS)
list(SORT _minipsd_sha1s)
list(JOIN _minipsd_sha1s "" _minipsd_sha1s)
string(SHA1 MINIPSD_SBOM_VERIFICATION "${_minipsd_sha1s}")
string(TIMESTAMP MINIPSD_SBOM_CREATED "%Y-%m-%dT%H:%M:%SZ" UTC)
configure_file(cmake/minipsd.spdx.json.in "${CMAKE_CURRENT_BINARY_DIR}/minipsd.spdx.json" @ONLY)
include(cmake/minipsd_spdx.cmake)
minipsd_spdx(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/minipsd.spdx.json" PACKAGE minipsd VERSION "${PROJECT_VERSION}"
HOMEPAGE "${PROJECT_HOMEPAGE_URL}" DOWNLOAD "git+${PROJECT_HOMEPAGE_URL}.git@${PROJECT_VERSION}"
SUMMARY "${PROJECT_DESCRIPTION}" COMMENT "Header-only: the files below, under include/, are the whole library."
BASE "${CMAKE_CURRENT_SOURCE_DIR}/include" PREFIX "include/" FILES ${_minipsd_headers})
set_target_properties(minipsd PROPERTIES MINIPSD_SBOM_FILE "${CMAKE_CURRENT_BINARY_DIR}/minipsd.spdx.json")

# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -170,5 +135,8 @@ endif()
if(MINIPSD_BUILD_TESTS)
enable_language(CXX)
enable_testing()
add_subdirectory(tests)
add_subdirectory(tests) # the plugin too, with the tests' warnings and its own test
elseif(MINIPSD_VIPS_PLUGIN)
include(cmake/minipsd_libvips.cmake)
add_subdirectory(libvips-plugin)
endif()
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Procreate open as layered documents.

# Status

**release: 0.3.1**
**release: 0.4.0**
The API is [include/minipsd.h](include/minipsd.h); the implementation is in
[include/minipsd/](include/minipsd/).

Expand Down Expand Up @@ -85,6 +85,10 @@ no deflate), and are copied as they are when such a file is read and written bac
files are bounded by caller limits. How it does on 315 files from
other programs: [docs/COMPATIBILITY.md](docs/COMPATIBILITY.md).

In a program built on libvips, [libvips-plugin/](libvips-plugin/) makes minipsd its PSD and PSB
loader and saver: a file's composite or any layer in, one image or several as layers out; see
the manual's [PSD in libvips](docs/MANUAL.md#psd-in-libvips-the-plugin).

## Adding it to a project

Copy the `include/` directory, or use CMake (FetchContent, git submodule, `find_package`),
Expand Down
22 changes: 11 additions & 11 deletions cmake/minipsd.spdx.json.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
"spdxVersion": "SPDX-2.3",
"dataLicense": "CC0-1.0",
"SPDXID": "SPDXRef-DOCUMENT",
"name": "minipsd-@PROJECT_VERSION@",
"documentNamespace": "@PROJECT_HOMEPAGE_URL@/spdx/minipsd-@PROJECT_VERSION@-@MINIPSD_SBOM_VERIFICATION@",
"name": "@S_PACKAGE@-@S_VERSION@",
"documentNamespace": "@S_HOMEPAGE@/spdx/@S_PACKAGE@-@S_VERSION@-@MINIPSD_SBOM_VERIFICATION@",
"creationInfo": {
"created": "@MINIPSD_SBOM_CREATED@",
"creators": [
Expand All @@ -13,12 +13,12 @@
},
"packages": [
{
"SPDXID": "SPDXRef-Package-minipsd",
"name": "minipsd",
"versionInfo": "@PROJECT_VERSION@",
"SPDXID": "SPDXRef-Package-@S_PACKAGE@",
"name": "@S_PACKAGE@",
"versionInfo": "@S_VERSION@",
"supplier": "Person: Bartlomiej Mucha (shadobadev@gmail.com)",
"downloadLocation": "git+@PROJECT_HOMEPAGE_URL@.git@@PROJECT_VERSION@",
"homepage": "@PROJECT_HOMEPAGE_URL@",
"downloadLocation": "@S_DOWNLOAD@",
"homepage": "@S_HOMEPAGE@",
"filesAnalyzed": true,
"packageVerificationCode": {
"packageVerificationCodeValue": "@MINIPSD_SBOM_VERIFICATION@"
Expand All @@ -27,13 +27,13 @@
"licenseDeclared": "MIT",
"licenseInfoFromFiles": [ "MIT" ],
"copyrightText": "Copyright (c) 2026 Bartlomiej Mucha <shadobadev@gmail.com>",
"summary": "@PROJECT_DESCRIPTION@",
"comment": "Header-only: the files below, under include/, are the whole library.",
"summary": "@S_SUMMARY@",
"comment": "@S_COMMENT@",
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:github/ShadobaDev/minipsd@@PROJECT_VERSION@"
"referenceLocator": "pkg:github/ShadobaDev/minipsd@@S_VERSION@"
}
]
}
Expand All @@ -44,7 +44,7 @@
{
"spdxElementId": "SPDXRef-DOCUMENT",
"relationshipType": "DESCRIBES",
"relatedSpdxElement": "SPDXRef-Package-minipsd"
"relatedSpdxElement": "SPDXRef-Package-@S_PACKAGE@"
},@MINIPSD_SBOM_CONTAINS@
]
}
76 changes: 76 additions & 0 deletions cmake/minipsd_libvips.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# ---------------------------------------------------------------------------
# libvips for what uses it: minipsd's libvips plugin (libvips-plugin/, MINIPSD_VIPS_PLUGIN; or the
# plugin as released, minipsd-vips-<version>.zip) and examples/vips_composite.c
# (MINIPSD_VIPS_EXAMPLE). minipsd itself never depends on libvips.
#
# Windows fetches libvips' official prebuilt "web" build, pinned (the newest release when set);
# elsewhere pkg-config finds the installed one. Gives:
#
# minipsd_libvips an imported target: libvips' C API, glib and gobject
# minipsd_libvips_zlib the zlib libvips links: Windows, the zip's libz1 (zlib-ng, built
# zlib-compatible; versions.json) with zlib's own headers, fetched and
# pinned, since the zip has none; elsewhere pkg-config's zlib
# MINIPSD_LIBVIPS_ENV the environment its tests run in (Windows: the DLLs on PATH), or ""
#
# A program with libvips of its own defines both targets before adding minipsd, visible to it (an
# INTERFACE library, or IMPORTED GLOBAL); nothing is then fetched or found here. A program that
# fetched libvips' Windows build itself sets FETCHCONTENT_SOURCE_DIR_MINIPSD_LIBVIPS to where it is
# unpacked: that one is used, and only zlib's headers are fetched.
# ---------------------------------------------------------------------------

if(TARGET minipsd_libvips AND TARGET minipsd_libvips_zlib)
set(MINIPSD_LIBVIPS_ENV "")
return()
endif()

if(WIN32)
set(MINIPSD_VIPS_VERSION 8.18.7)
include(FetchContent)
FetchContent_Declare(minipsd_libvips # named as its target: a program may call the plugin minipsd_vips
URL https://github.com/libvips/build-win64-mxe/releases/download/v${MINIPSD_VIPS_VERSION}/vips-dev-x64-web-${MINIPSD_VIPS_VERSION}.zip
URL_HASH SHA256=3a122eb3d588690008216f786338e2f9329dba3c3c2768b5933cf7299d549241
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
SOURCE_SUBDIR no-cmake-project) # files only: nothing to add as a subproject
FetchContent_MakeAvailable(minipsd_libvips)
set(_vips "${minipsd_libvips_SOURCE_DIR}")
add_library(minipsd_libvips INTERFACE IMPORTED)
if(MSVC) # the zip's import libraries
target_link_libraries(minipsd_libvips INTERFACE
"${_vips}/lib/libvips.lib" "${_vips}/lib/libglib-2.0.lib" "${_vips}/lib/libgobject-2.0.lib")
else() # MinGW links the DLLs themselves
target_link_libraries(minipsd_libvips INTERFACE
"${_vips}/bin/libvips-42.dll" "${_vips}/bin/libglib-2.0-0.dll" "${_vips}/bin/libgobject-2.0-0.dll")
endif()
target_include_directories(minipsd_libvips SYSTEM INTERFACE
"${_vips}/include" "${_vips}/include/glib-2.0" "${_vips}/lib/glib-2.0/include")
# zlib's headers for the zlib-ng the zip links: built zlib-compatible, it is zlib 1.3.1's ABI
# (libz1.dll of 8.18.7, zlib-ng 2.3.3, reports zlibVersion() "1.3.1.zlib-ng"; deflateInit_
# checks the version's first digit and sizeof(z_stream)). zlib-ng's own headers are made when
# it is built (zlib.h.in, zconf.h.in), so no release has them to fetch; madler's 1.3.1 are
# the same API and layout. Bump them with libvips, to the zlib version its libz1 reports.
FetchContent_Declare(minipsd_zlib_headers
URL https://github.com/madler/zlib/releases/download/v1.3.1/zlib-1.3.1.tar.gz
URL_HASH SHA256=9a93b2b7dfdac77ceba5a558a580e74667dd6fede4585b91eefb60f03b72df23
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
SOURCE_SUBDIR no-cmake-project) # zlib.h and zconf.h only
FetchContent_MakeAvailable(minipsd_zlib_headers)
add_library(minipsd_libvips_zlib INTERFACE IMPORTED)
target_include_directories(minipsd_libvips_zlib SYSTEM INTERFACE "${minipsd_zlib_headers_SOURCE_DIR}")
if(MSVC)
target_link_libraries(minipsd_libvips_zlib INTERFACE "${_vips}/lib/libz1.lib")
else()
target_link_libraries(minipsd_libvips_zlib INTERFACE "${_vips}/bin/libz1.dll")
endif()
set(_vips_path "${_vips}/bin;$ENV{PATH}") # the DLLs, for the tests
string(REPLACE ";" "\\;" _vips_path "${_vips_path}")
set(MINIPSD_LIBVIPS_ENV "PATH=${_vips_path}")
else()
find_package(PkgConfig REQUIRED)
pkg_check_modules(VIPS REQUIRED IMPORTED_TARGET vips)
add_library(minipsd_libvips INTERFACE IMPORTED)
target_link_libraries(minipsd_libvips INTERFACE PkgConfig::VIPS)
pkg_check_modules(VIPS_ZLIB REQUIRED IMPORTED_TARGET zlib)
add_library(minipsd_libvips_zlib INTERFACE IMPORTED)
target_link_libraries(minipsd_libvips_zlib INTERFACE PkgConfig::VIPS_ZLIB)
set(MINIPSD_LIBVIPS_ENV "")
endif()
Loading
Loading