Summary
When the system PATH environment variable contains empty entries (e.g., ;; on Windows or :: on Unix), find_package() unexpectedly searches the current working directory. This happens because empty PATH entries are passed to path resolution functions that convert "" to CWD.
I’d like to discuss whether filtering empty PATH entries in find_package() would be a reasonable enhancement.
The Issue
On Windows, it’s common for the system PATH to contain empty entries:
- Trailing semicolon:
C:\bin;C:\tools; - Double semicolons:
C:\bin;;C:\tools
These malformed entries often come from buggy installers and are difficult for users to notice.
When find_package() processes CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH, it iterates through PATH entries. Empty entries get passed to CollapseFullPath(""), which correctly resolves them to the current working directory (since "" is a valid relative path meaning “current directory”).
Reproduction
cmake_minimum_required(VERSION 3.20)
project(test)
# Simulate empty PATH entry
set(ENV{PATH} "C:/bin;;C:/tools")
# Create a config file in build directory
file(WRITE "${CMAKE_BINARY_DIR}/mylib-config.cmake" "set(mylib_FOUND TRUE)")
# This finds mylib because "" resolves to CMAKE_BINARY_DIR
find_package(mylib CONFIG QUIET)
if(mylib_FOUND)
message(WARNING "mylib found unexpectedly in: ${mylib_DIR}")
endif()
Impact
This becomes problematic when:
- CMake runs with CWD set to the build directory (common in IDE integrations)
- The build directory contains
*-config.cmakefiles fromexport(TARGETS ...) - System PATH has empty entries
In this case, find_package(foo) may incorrectly find packages exported to the build tree, even when foo_ROOT or CMAKE_PREFIX_PATH isn’t set.
Proposal
Would it be reasonable for CMake to filter empty entries when processing PATH for find_package() searches? Something like:
// When iterating PATH entries for find_package search
if (pathEntry.empty()) {
continue; // Skip empty entries
}
This would be a defensive enhancement that prevents unexpected behavior from malformed PATH variables, which are unfortunately common on Windows systems.
Workaround
Currently, users can work around this by filtering PATH at the start of CMakeLists.txt:
if(WIN32)
set(_path_sep ";")
else()
set(_path_sep ":")
endif()
string(REPLACE "${_path_sep}" ";" _path_entries "$ENV{PATH}")
list(FILTER _path_entries EXCLUDE REGEX "^$")
list(JOIN _path_entries "${_path_sep}" _filtered_path)
set(ENV{PATH} "${_filtered_path}")
Questions
- Is this considered expected behavior, or would filtering empty PATH entries be a welcome enhancement?
- If this is worth pursuing, should I file a GitLab issue?
Thanks for any feedback!