# Poorly-explained cmake\_path() subcommands (CMake 3.19)

**URL:** <https://discourse.cmake.org/t/poorly-explained-cmake-path-subcommands-cmake-3-19/1861>\
**Category:** Code\
**Created:** [September 19, 2020, 2:06pm UTC](https://discourse.cmake.org/t/poorly-explained-cmake-path-subcommands-cmake-3-19/1861 "2020-09-19T14:06:05Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![ferdnyc](https://discourse.cmake.org/user_avatar/discourse.cmake.org/ferdnyc/32/267_2.png) [@ferdnyc](https://discourse.cmake.org/u/ferdnyc)\
**Post date:** [September 19, 2020, 2:06pm UTC](https://discourse.cmake.org/t/poorly-explained-cmake-path-subcommands-cmake-3-19/1861/1 "2020-09-19T14:06:05Z")

</div>

I was reading through [the documentation for the upcoming `cmake_path()` command](https://cmake.org/cmake/help/git-stage/command/cmake_path.html) that will replace most of the `file(foo_PATH ...)` subcommands in the next release, and I’m finding some of them… both non-obvious, and unhelpfully documented.

`IS_RELATIVE` and `IS_ABSOLUTE`, those make sense to me, their workings are obvious. Many of the rest, though…

> `cmake_path(HAS_ROOT_NAME <path> <output>)`
> 
> Checks if `<path>` has `root-name` .
> 
> `cmake_path(HAS_ROOT_DIRECTORY <path> <output>)`
> 
> Checks if `<path>` has `root-directory` .

Since these aren’t documented as taking _inputs_ for `root-name` and `root-directory`, I have no real idea what they’re supposed to do.

> `cmake_path(HAS_ROOT_PATH <path> <output>)`
> 
> Checks if `<path>` has root path.
> 
> Effectively, checks the following: `root-name / root-directory` .

Given the above, this one is even _more_ confusing.

> `cmake_path(HAS_FILENAME <path> <output>)`
> 
> Checks if `<path>` has `file-name` .

Again, since `file-name` isn’t an input, I’m confused. I’d assume this checks whether the path has _any_ filename — meaning, it doesn’t end in a slash. But then `file-name` should just be “a filename component” or something like that.

> `cmake_path(HAS_EXTENSION <path> <output>)`
> 
> Checks if `<path>` has an [\<extension](https://cmake.org/cmake/help/git-stage/command/cmake_path.html#extension-def). If the first character in the filename is a period, it is not treated as an extension (for example “.profile”).

This makes me even more convinced I’m correct about the previous one, since they would be complementary.

> `cmake_path(HAS_STEM <path> <output>)`
> 
> Checks if `<path>` has stem.

Aaaand, we’re back to “I have no idea what this means”.

> `cmake_path(HAS_RELATIVE_PATH <path> <output>)`
> 
> Checks if `<path>` has relative path.

How is this different from “IS\_RELATIVE”? They sound redundant.

> `cmake_path(HAS_PARENT_PATH <path> <output>)`
> 
> Checks if `<path>` has parent path.

Yup, again, no clue what that means. How can a path “have” a parent path — and not even a _specific_ one, just any _arbitrary_ parent path?

A pair of commands like…

```cmake
cmake_path(IS_PARENT_OF <path> <child> <output>)
cmake_path(IS_CHILD_OF <path> <parent> <output>)

```

_that_ would make sense to me. I could totally see the utility in that. And, actually, I guess that first one is `cmake_path(IS_PREFIX_OF <path> <input>)`, so that’s cool. And I suppose you could just reverse `<path>` and `<input>` to get the other operation. So that only leaves me, again, even more confused about what all those other commands are supposed to be doing.

I just can’t figure out _how_, _when_, or _why_ most of these would be used. And the current documentation only makes it _less_ clear.

---

<div class="post-metadata">

**Author:** ![ferdnyc](https://discourse.cmake.org/user_avatar/discourse.cmake.org/ferdnyc/32/267_2.png) [@ferdnyc](https://discourse.cmake.org/u/ferdnyc)\
**Post date:** [September 19, 2020, 2:19pm UTC](https://discourse.cmake.org/t/poorly-explained-cmake-path-subcommands-cmake-3-19/1861/2 "2020-09-19T14:19:15Z")

</div>

OK, the introduction waaay at the top makes _some_ of this clearer. And makes other parts of it appear to be downright wrong.

> The path name has the following syntax:
> 
> 1. `root-name` (optional): identifies the root on a filesystem with multiple roots (such as `"C:"` or `"//myserver"` ).
> 2. `root-directory` (optional): a directory separator that, if present, marks this path as absolute. If it is missing (and the first element other than the root name is a file name), then the path is relative.

…Okay, but if `root-directory` is the directory _separator_, then “Effectively, checks the following: `root-name / root-directory`.” seems patently false. It checks that the path starts with `root-name` `root-directory`. (Where `root-name` will always be empty on Linux.)

Also, “and the first element other than the root name is a file name” should surely say “…is a file name or directory name”. Actually, even _that’s_ not right. The first element could also be `.` or `..`.

---

<div class="post-metadata">

**Author:** ![marc.chevrier](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/ecb155/32.png) [@marc.chevrier](https://discourse.cmake.org/u/marc.chevrier)\
**Post date:** [September 19, 2020, 2:35pm UTC](https://discourse.cmake.org/t/poorly-explained-cmake-path-subcommands-cmake-3-19/1861/3 "2020-09-19T14:35:31Z")

</div>

Thanks for your remarks.

A less aggressive and more constructive tone would have been welcome …

---

<div class="post-metadata">

**Author:** ![ferdnyc](https://discourse.cmake.org/user_avatar/discourse.cmake.org/ferdnyc/32/267_2.png) [@ferdnyc](https://discourse.cmake.org/u/ferdnyc)\
**Post date:** [September 19, 2020, 2:38pm UTC](https://discourse.cmake.org/t/poorly-explained-cmake-path-subcommands-cmake-3-19/1861/4 "2020-09-19T14:38:48Z")

</div>

My apologies.

---

<div class="post-metadata">

**Author:** ![ferdnyc](https://discourse.cmake.org/user_avatar/discourse.cmake.org/ferdnyc/32/267_2.png) [@ferdnyc](https://discourse.cmake.org/u/ferdnyc)\
**Post date:** [September 19, 2020, 2:54pm UTC](https://discourse.cmake.org/t/poorly-explained-cmake-path-subcommands-cmake-3-19/1861/5 "2020-09-19T14:54:16Z")

</div>

_Constructively_, I would strongly recommend against adopting this definition:

> Zero or more of the following:
> 
> 1. `file-name` : sequence of characters that aren’t directory separators. This name may identify a file, a hard link, a symbolic link, or a directory. Two special file-names are recognized:
> 
> > - `dot` : the file name consisting of a single dot character `.` is a directory name that refers to the current directory.
> > - `dot-dot` : the file name consisting of two dot characters `..` is a directory name that refers to the parent directory.
> 
> 1. `directory-separator` : the forward slash character `/` . If this character is repeated, it is treated as a single directory separator: `/usr///////lib` is the same as `/usr/lib` .

It would be better to describe that as a `path-component` or a `name-string` than as a `file-name`, as defining a “filename” as “the name of a file, or a directory, or `.` or `..`” only confuses things mightily.

> A `file-name` can have an extension. By default, the extension is defined as the sub-string beginning at the leftmost period (including the period) and until the end of the pathname. When the option `LAST_ONLY` is specified, the extension is the sub-string beginning at the rightmost period.

This definition should also be expanded: An extension is a substring _only_ of the **last** `path-component` (the one following the rightmost `directory-separator`) — other `path-component`s cannot have extensions, even if they contain a period.

And as is mentioned later in the docs, the extension can’t start at the first character of the `path-component`. If the final `path-component` is `.profile`, it has no extension. If the final `path-component` is `.config.txt`, its extension is just `.txt` with _or_ without `LAST_ONLY`.

---

<div class="post-metadata">

**Author:** ![marc.chevrier](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/ecb155/32.png) [@marc.chevrier](https://discourse.cmake.org/u/marc.chevrier)\
**Post date:** [September 19, 2020, 3:04pm UTC](https://discourse.cmake.org/t/poorly-explained-cmake-path-subcommands-cmake-3-19/1861/6 "2020-09-19T15:04:59Z")

</div>

`file-name` can be confusing, I agree, but `path-component` is ambiguous as well because `root-name` or `root-directory` are also components of the path.

FYI, `cmake_path` command is translation in `CMake` environment of `std::filesystem::path` STL class so I try to keep the same semantic and wording… And the documentation use the term `file-name`.

---

<div class="post-metadata">

**Author:** ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)\
**Post date:** [October 24, 2020, 7:06am UTC](https://discourse.cmake.org/t/poorly-explained-cmake-path-subcommands-cmake-3-19/1861/7 "2020-10-24T07:06:18Z")

</div>

I’m happy to rework the docs during this 3.19 release cycle to improve their clarity, but first I’d like to see discussion of some concerns I’ve just raised in [another post](https://discourse.cmake.org/t/inconsistent-behavior-of-cmake-path-subcommands-taking-a-variable-name-instead-of-a-string/2062) run its course.

---

<div class="post-metadata">

**Author:** ![marc.chevrier](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/ecb155/32.png) [@marc.chevrier](https://discourse.cmake.org/u/marc.chevrier)\
**Post date:** [October 24, 2020, 9:56am UTC](https://discourse.cmake.org/t/poorly-explained-cmake-path-subcommands-cmake-3-19/1861/8 "2020-10-24T09:56:38Z")

</div>

Thanks for your proposition. FYI, I reply to your previous post.

---

<div class="post-metadata">

**Author:** ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)\
**Post date:** [November 1, 2020, 11:51am UTC](https://discourse.cmake.org/t/poorly-explained-cmake-path-subcommands-cmake-3-19/1861/9 "2020-11-01T11:51:54Z")

</div>

Please see related discussions in [this issue](https://gitlab.kitware.com/cmake/cmake/-/issues/21385) in the issue tracker.

---

<div class="post-metadata">

**Author:** ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)\
**Post date:** [November 8, 2020, 8:30am UTC](https://discourse.cmake.org/t/poorly-explained-cmake-path-subcommands-cmake-3-19/1861/10 "2020-11-08T08:30:24Z")

</div>

@ferdnyc I’ve added a [proposed revised version](https://gitlab.kitware.com/cmake/cmake/-/issues/21385#note_855713) of the API for discussion in the associated issue. We would appreciate it if you could take a look and perhaps provide feedback in that issue with your thoughts.

---

<div class="post-metadata">

**Author:** ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)\
**Post date:** [January 9, 2021, 5:05am UTC](https://discourse.cmake.org/t/poorly-explained-cmake-path-subcommands-cmake-3-19/1861/11 "2021-01-09T05:05:08Z")

</div>

@ferdnyc I finally got a chance to rework the docs for `cmake_path()`. Would appreciate your feedback on the changes (I expect there will be more reworking to do after review).

[https://gitlab.kitware.com/cmake/cmake/-/merge\_requests/5682](https://gitlab.kitware.com/cmake/cmake/-/merge_requests/5682)

---

<div class="post-metadata">

**Author:** ![ferdnyc](https://discourse.cmake.org/user_avatar/discourse.cmake.org/ferdnyc/32/267_2.png) [@ferdnyc](https://discourse.cmake.org/u/ferdnyc)\
**Post date:** [January 10, 2021, 1:36am UTC](https://discourse.cmake.org/t/poorly-explained-cmake-path-subcommands-cmake-3-19/1861/12 "2021-01-10T01:36:34Z")

</div>

@craig.scott I’ll take a look, thanks!

Apologies for not responding to your previous request. To be honest I’d sort of checked out of this one, it’s been months since I last looked at this topic. I’d clearly made a poor first impression, and the whole interaction felt tainted, so the only thing that seemed likely to come out of pressing the issue further was digging myself an even deeper hole.

(Or, in its more recognizable form, “Better to remain silent and be thought a fool than to speak and to remove all doubt.”)
