# cmake\_path(ABSOLUTE\_PATH ...) vs. get\_filename\_component(... ABSOLUTE)

**URL:** https://discourse.cmake.org/t/cmake-path-absolute-path-vs-get-filename-component-absolute/5549
**Category:** Usage
**Created:** [April 26, 2022, 7:41pm UTC](https://discourse.cmake.org/t/cmake-path-absolute-path-vs-get-filename-component-absolute/5549 "2022-04-26T19:41:30Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![johan556](https://discourse.cmake.org/user_avatar/discourse.cmake.org/johan556/32/788_2.png) [@johan556](https://discourse.cmake.org/u/johan556)
#### Post date: [April 26, 2022, 7:41pm UTC](https://discourse.cmake.org/t/cmake-path-absolute-path-vs-get-filename-component-absolute/5549/1 "2022-04-26T19:41:30Z")

</div>

I tried to use cmake\_path() instead of get\_filename\_component() to “normalize” a path. But when I start with `"/x/y/z/w/../.."` I get these results:

```auto
-- cmake_path: /x/y/
-- get_filename_component: /x/y

```

Is there any way I can get rid of the trailing “/” in the cmake\_path() case?  
I don’t know if I’m missing some way to get cmake\_path() to do the same as get\_filename\_component()?

And is this an intentional difference, or just a consequence of using `lexically_normal()` from the `<filesystem>` header in recent C++ versions?

My example script looks like:

```auto
set(aaa /x/y/z/w/../..)
cmake_path(ABSOLUTE_PATH aaa NORMALIZE)
message(STATUS "cmake_path: ${aaa}")

set(aaa /x/y/z/w/../..)
get_filename_component(res "${aaa}" ABSOLUTE)
message(STATUS "get_filename_component: ${res}")

```

Regards,  
Johan Holmberg

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [April 26, 2022, 7:53pm UTC](https://discourse.cmake.org/t/cmake-path-absolute-path-vs-get-filename-component-absolute/5549/2 "2022-04-26T19:53:08Z")

</div>

Cc: @marc.chevrier

---

<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: [April 26, 2022, 8:54pm UTC](https://discourse.cmake.org/t/cmake-path-absolute-path-vs-get-filename-component-absolute/5549/3 "2022-04-26T20:54:13Z")

</div>

The trailing ‘/’ is here on purpose. It enables to distinguish between a directory name and file name.

`cmake_path` has a strong semantic over paths, so they are not handled exactly in the same way as `get_filename_component`.

There is no way to remove it. What for do you want to do that, anyway?

---

<div class="post-metadata">

### Author: ![johan556](https://discourse.cmake.org/user_avatar/discourse.cmake.org/johan556/32/788_2.png) [@johan556](https://discourse.cmake.org/u/johan556)
#### Post date: [April 27, 2022, 5:15am UTC](https://discourse.cmake.org/t/cmake-path-absolute-path-vs-get-filename-component-absolute/5549/4 "2022-04-27T05:15:55Z")

</div>

Our CMake code has many places where new paths are used/created “inline” in the code like `"${MY_DIR}/my_subdir"`. If `MY_DIR` is the result of a call to `cmake_path()` like I described earlier, will not the resulting path look like `"/x/y//my_subdir"` ? Maybe this works and the double “//” is harmless, but is it always so? Even if CMake itself handles this, what about if for example custom commands get such a path?

As I understand, all variables in CMake are still strings in the end. And having to think in each case if a variable representing a directory has a trailing “/” or not seems doomed to cause trouble.

The documentation said that `get_filename_component()` is "superseded by `cmake_path()`", so I thought that I should move aways from using the old function. But until I understand how to handle this “//” situation, I think I will have to stick with `get_filename_component()`. Rewriting all code to use `cmake_path()` seems like too much work with an existing codebase.

---

<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: [April 27, 2022, 7:35am UTC](https://discourse.cmake.org/t/cmake-path-absolute-path-vs-get-filename-component-absolute/5549/5 "2022-04-27T07:35:17Z")

</div>

Having a double ‘/’ in paths is completely harmless in `CMake`.

For custom commands, on Unix and Unix like systems, I am not aware of tools having problems with such paths. On Windows, it could be more problematic, but anyway, the right thing to do is to transform the CMake path to native path to avoid any trouble (use `cmake_path(NATIVE_PATH)` or `cmake_path(CONVERT ... TO_NATIVE_PATH_LIST)` commands for that purpose).

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [April 27, 2022, 10:17am UTC](https://discourse.cmake.org/t/cmake-path-absolute-path-vs-get-filename-component-absolute/5549/6 "2022-04-27T10:17:19Z")

</div>

> [@marc.chevrier](#):
>
> For custom commands, on Unix and Unix like systems, I am not aware of tools having problems with such paths.

`rsync` doesn’t care about inner double `/` situations, but a trailing one does change how it works. Other tools act this way too (primarily when it is a directory symlink in the “target” position for various Unix tools).

---

<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: [April 27, 2022, 10:38am UTC](https://discourse.cmake.org/t/cmake-path-absolute-path-vs-get-filename-component-absolute/5549/7 "2022-04-27T10:38:37Z")

</div>

And how the behavior is changed ?

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [April 27, 2022, 10:44am UTC](https://discourse.cmake.org/t/cmake-path-absolute-path-vs-get-filename-component-absolute/5549/8 "2022-04-27T10:44:28Z")

</div>

`rsync` treats trailing-`/` paths to mean “contents of” rather than the directory itself.

`rsync -r foo/ bar` will copy `foo`'s contents into `bar` while `rsync -r foo bar` will create `bar/foo`. Playing around a bit, the “target” position isn’t such an easy rule, so it really depends on the tool being used there it seems.

---

<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: [April 27, 2022, 2:23pm UTC](https://discourse.cmake.org/t/cmake-path-absolute-path-vs-get-filename-component-absolute/5549/9 "2022-04-27T14:23:46Z")

</div>

I see. What a weird idea to change the semantics of the path!!

I agree, with such approaches in the wild, it is required to be very attentive of arguments delivered to third party tools…

---

<div class="post-metadata">

### Author: ![MarcH](https://discourse.cmake.org/user_avatar/discourse.cmake.org/march/32/2783_2.png) [@MarcH](https://discourse.cmake.org/u/MarcH)
#### Post date: [September 19, 2022, 9:29pm UTC](https://discourse.cmake.org/t/cmake-path-absolute-path-vs-get-filename-component-absolute/5549/10 "2022-09-19T21:29:18Z")

</div>

> [@marc.chevrier](#):
>
> I see. What a weird idea to change the semantics of the path!!

This is surprising at first but very useful: it helps to make `rsync` idempotent/deterministic.

If B does not exist yet and you `cp -r A B` twice then the first and second invocation will do two different things… on some operating systems. On other operating systems it is idempotent. It’s a mess.

The trailing slash is rsync’s way to force you to say exactly which one you want.

I stopped using `cp -r` a long time ago, I only use rsync now.
