Should find_package() skip empty PATH entries?

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:

  1. CMake runs with CWD set to the build directory (common in IDE integrations)
  2. The build directory contains *-config.cmake files from export(TARGETS ...)
  3. 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

  1. Is this considered expected behavior, or would filtering empty PATH entries be a welcome enhancement?
  2. If this is worth pursuing, should I file a GitLab issue?

Thanks for any feedback!

Thanks for pointing this out. Yes, please open an issue.

Issue opened: https://gitlab.kitware.com/cmake/cmake/-/issues/27454