Skip to content

Allow directory as inputs, i.e. input paths ending in / - #2815

Open
jhasse wants to merge 1 commit into
masterfrom
directory-nodes
Open

Allow directory as inputs, i.e. input paths ending in /#2815
jhasse wants to merge 1 commit into
masterfrom
directory-nodes

Conversation

@jhasse

@jhasse jhasse commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

See #2709.

Comment thread doc/manual.asciidoc
If an input path on a build line ends with a path separator (`/`), the input is
treated as a directory rather than a regular file. When Ninja checks whether the
build edge is up-to-date, it stats the directory itself and compares its
modification time against the outputs.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this phrase is confusing because Ninja already stats directory paths if there is no trailing slash. And I am sure that someone is using this in their build system, even if it is a fragile thing to do, so this behavior cannot be changed lightly.

A better phrasing might explain what the trailing slash does, e.g.:

"""
An input path with a trailing separator (e.g. foo/bar/) must always point to a valid directory, otherwise Ninja will complain with an error. By contrast, paths without it (e.g. foo/bar) can point to either a file or a directory.

In both cases, the timestamp used by Ninja corresponds to the file-system's directory entry itself (which does not change when the files within it are modified).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I must say that I fail to see the benefit of this PR. I assumed it is to prepare for glob support but that would require another non-trivial change of logic in Ninja, so why introduce it here and not as a preliminary commit in a PR that does that?

Comment thread src/graph.h
/// True if this node refers to a directory rather than a regular file.
/// Set when a manifest input/output path ends with a trailing slash. When
/// stat()ing, the path is treated as a directory and its mtime is used.
bool is_directory_ = false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: there is no need for a boolean flag. Just use path_.back() == '/' here.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually scratch that, it depends if you want to treat foo/ and foo in the same manifest as pointing to the same graph Node. From this code it looks like that if there is at least one use of foo/ in the manifest for an input path, then the Node for foo is marked as a directory, even if other uses are not.

This is quite subtle, and also doesn't happen if foo is an output, or comes from a depfile, or a dyndep file.

It would probably make more sense to just check for the trailing separator when adding a new Node instead to cover all cases, otherwise this will lead to very hard-to-debug inconsistencies.

Comment thread doc/manual.asciidoc
- list the affected files explicitly (or via a depfile) if that is desired.

A path with a trailing separator that exists but is not a directory is treated
as missing.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem to correspond to the implementation. If the path points to a file, it will be reported as an error ??

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants