Skip to content

which() does not use PATHEXT on Windows #2926

@cspotcode

Description

@cspotcode

Subtly different from #2826

Reproduced on just 1.43.0.

The built-in which() and require() commands fails to find executables on Windows because they do not follow Windows conventions for executable lookup: use PATH and PATHEXT.

For example:

# Suppose I am writing a cross-platform justfile

set unstable

# require_git_path_fails_windows := require('git')
# Logs error:
#    error: Call to function `require` failed: could not find executable `git`

# This succeeds on Windows but fails on Linux
require_git_path_succeeds_windows := require('git.exe')

git_path_empty_string_on_windows := which('git')
git_path_found_on_windows := which('git.exe')

# Is forcing extra syntax to be cross-platform desirable?
# What value comes from forcing this extra syntax, as opposed to finding the desired path on all systems without it?
# On Windows, executables are invoked without explicit extension and have extension on the filesystem.
git_path_cross_platform := if os() == "windows" { which("git.exe") } else { which("git") }

@default:
    echo "require_git_path_succeeds_windows = {{require_git_path_succeeds_windows}}"
    echo "git_path_empty_string_on_windows = {{git_path_empty_string_on_windows}}"
    echo "git_path_found_on_windows = {{git_path_found_on_windows}}"
    echo "git_path_cross_platform = {{git_path_cross_platform}}"

Some people may feel that checking $PATHEXT is a windows-specific hack that just shouldn't implement. But I disagree.

Just as filesystem logic must use \s on Windows, and the $PATH parser must split on ; instead of :, so too must implementations of which look at $PATHEXT. This is baked into the way $PATH works on Windows: it only makes sense paired with $PATHEXT. You will never find a file named git on the Windows path. It will never exist. You will find git.exe.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions