mirror of
https://github.com/opencv/opencv.git
synced 2026-07-21 19:33:03 +04:00
e640a9bfb8
cmake: fix PNG status display when BUILD_PNG=ON #28995 ### Description Fixes #28657. On macOS (and other Apple platforms), `BUILD_PNG=ON` is the default. The build system correctly clears `PNG_FOUND` in `OpenCVFindLibsGrfmt.cmake` and builds libpng from the bundled source. However, during the subsequent module processing phase, a downstream `find_package(PNG)` call — triggered transitively via `include()` in the **same scope** — overwrites not only `PNG_FOUND`, but also `PNG_INCLUDE_DIR`, `PNG_LIBRARIES`, and `PNG_VERSION_STRING`. #### Root Cause: FindPNG.cmake Has Asymmetric Guards Reading CMake 4.3's `FindPNG.cmake` (`/opt/homebrew/share/cmake/Modules/FindPNG.cmake`) reveals: | Variable | Guard? | Fate | |---|---|---| | `PNG_LIBRARY` | `if(NOT PNG_LIBRARY)` at line 138 — **guarded** | Preserved | | `PNG_PNG_INCLUDE_DIR` | `find_path(...)` at line 115 — **no guard** | **Overwritten** | | `PNG_INCLUDE_DIR` | Derived from `PNG_PNG_INCLUDE_DIR` | **Chain-overwritten** | | `PNG_LIBRARIES` | Derived from `PNG_LIBRARY` + `ZLIB_LIBRARY` | **Partly overwritten** | | `PNG_VERSION_STRING` | Parsed from `PNG_PNG_INCLUDE_DIR/png.h` | **Overwritten** | `PNG_LIBRARY` survives because FindPNG itself checks `if(NOT PNG_LIBRARY)`. But `find_path(PNG_PNG_INCLUDE_DIR)` runs unconditionally — re-searching and overwriting the bundled path with the system one. #### Fix: Three Coordinated Changes **Part A — Status guard** (`CMakeLists.txt`): When `BUILD_PNG=ON`, pass `FALSE` as the condition to always show `"build"` regardless of `PNG_FOUND`. **Part B — Variable lock** (`cmake/OpenCVFindLibsGrfmt.cmake`): After building from bundled source, lock `PNG_PNG_INCLUDE_DIR` as `CACHE INTERNAL`. CMake's `find_path()` checks the cache first — if the variable exists with a valid path, it skips re-searching. The system path is never found. **Part C — Cache cleanup** (`cmake/OpenCVFindLibsGrfmt.cmake`): Add `PNG_PNG_INCLUDE_DIR` to the `ocv_clear_internal_cache_vars()` call in the `else` branch. When a user switches `BUILD_PNG=OFF`, the cached variable is cleared, allowing `find_path` to search for the system libpng normally. Prevents stale cache leakage across configuration changes. #### Verification (macOS 26, CMake 4.3, Homebrew libpng 1.6.58) ``` BEFORE downstream find_package(PNG): PNG_LIBRARY = libpng PNG_INCLUDE_DIR = .../3rdparty/libpng PNG_VERSION_STRING = 1.6.37 AFTER downstream find_package(PNG) [with fix]: PNG_LIBRARY = libpng ← preserved (FindPNG guard) PNG_INCLUDE_DIR starts with .../3rdparty/libpng ← locked (Part B) PNG_VERSION_STRING = 1.6.53 ← from bundled png.h Status display: build (ver 1.6.53) ← correct (Part A) ``` The full reproduction and analysis are in the attached `bugReview/` directory. ### Checklist - [x] There is a reference to the original bug report and related work - [x] The test case is in `bugReview/` directory - [x] Tested on macOS 26 (arm64) with CMake 4.3 + Homebrew libpng 1.6.58 - [x] Cache hygiene verified for BUILD_PNG ON→OFF→ON transitions