1cmake_path
2----------
3
4.. versionadded:: 3.20
5
6This command is for the manipulation of paths.  Only syntactic aspects of
7paths are handled, there is no interaction of any kind with any underlying
8file system.  The path may represent a non-existing path or even one that
9is not allowed to exist on the current file system or platform.
10For operations that do interact with the filesystem, see the :command:`file`
11command.
12
13.. note::
14
15  The ``cmake_path`` command handles paths in the format of the build system
16  (i.e. the host platform), not the target system.  When cross-compiling,
17  if the path contains elements that are not representable on the host
18  platform (e.g. a drive letter when the host is not Windows), the results
19  will be unpredictable.
20
21Synopsis
22^^^^^^^^
23
24.. parsed-literal::
25
26  `Conventions`_
27
28  `Path Structure And Terminology`_
29
30  `Normalization`_
31
32  `Decomposition`_
33    cmake_path(`GET`_ <path-var> :ref:`ROOT_NAME <GET_ROOT_NAME>` <out-var>)
34    cmake_path(`GET`_ <path-var> :ref:`ROOT_DIRECTORY <GET_ROOT_DIRECTORY>` <out-var>)
35    cmake_path(`GET`_ <path-var> :ref:`ROOT_PATH <GET_ROOT_PATH>` <out-var>)
36    cmake_path(`GET`_ <path-var> :ref:`FILENAME <GET_FILENAME>` <out-var>)
37    cmake_path(`GET`_ <path-var> :ref:`EXTENSION <GET_EXTENSION>` [LAST_ONLY] <out-var>)
38    cmake_path(`GET`_ <path-var> :ref:`STEM <GET_STEM>` [LAST_ONLY] <out-var>)
39    cmake_path(`GET`_ <path-var> :ref:`RELATIVE_PART <GET_RELATIVE_PART>` <out-var>)
40    cmake_path(`GET`_ <path-var> :ref:`PARENT_PATH <GET_PARENT_PATH>` <out-var>)
41
42  `Query`_
43    cmake_path(`HAS_ROOT_NAME`_ <path-var> <out-var>)
44    cmake_path(`HAS_ROOT_DIRECTORY`_ <path-var> <out-var>)
45    cmake_path(`HAS_ROOT_PATH`_ <path-var> <out-var>)
46    cmake_path(`HAS_FILENAME`_ <path-var> <out-var>)
47    cmake_path(`HAS_EXTENSION`_ <path-var> <out-var>)
48    cmake_path(`HAS_STEM`_ <path-var> <out-var>)
49    cmake_path(`HAS_RELATIVE_PART`_ <path-var> <out-var>)
50    cmake_path(`HAS_PARENT_PATH`_ <path-var> <out-var>)
51    cmake_path(`IS_ABSOLUTE`_ <path-var> <out-var>)
52    cmake_path(`IS_RELATIVE`_ <path-var> <out-var>)
53    cmake_path(`IS_PREFIX`_ <path-var> <input> [NORMALIZE] <out-var>)
54    cmake_path(`COMPARE`_ <input1> <OP> <input2> <out-var>)
55
56  `Modification`_
57    cmake_path(:ref:`SET <cmake_path-SET>` <path-var> [NORMALIZE] <input>)
58    cmake_path(`APPEND`_ <path-var> [<input>...] [OUTPUT_VARIABLE <out-var>])
59    cmake_path(`APPEND_STRING`_ <path-var> [<input>...] [OUTPUT_VARIABLE <out-var>])
60    cmake_path(`REMOVE_FILENAME`_ <path-var> [OUTPUT_VARIABLE <out-var>])
61    cmake_path(`REPLACE_FILENAME`_ <path-var> <input> [OUTPUT_VARIABLE <out-var>])
62    cmake_path(`REMOVE_EXTENSION`_ <path-var> [LAST_ONLY] [OUTPUT_VARIABLE <out-var>])
63    cmake_path(`REPLACE_EXTENSION`_ <path-var> [LAST_ONLY] <input> [OUTPUT_VARIABLE <out-var>])
64
65  `Generation`_
66    cmake_path(`NORMAL_PATH`_ <path-var> [OUTPUT_VARIABLE <out-var>])
67    cmake_path(`RELATIVE_PATH`_ <path-var> [BASE_DIRECTORY <input>] [OUTPUT_VARIABLE <out-var>])
68    cmake_path(`ABSOLUTE_PATH`_ <path-var> [BASE_DIRECTORY <input>] [NORMALIZE] [OUTPUT_VARIABLE <out-var>])
69
70  `Native Conversion`_
71    cmake_path(`NATIVE_PATH`_ <path-var> [NORMALIZE] <out-var>)
72    cmake_path(`CONVERT`_ <input> `TO_CMAKE_PATH_LIST`_ <out-var> [NORMALIZE])
73    cmake_path(`CONVERT`_ <input> `TO_NATIVE_PATH_LIST`_ <out-var> [NORMALIZE])
74
75  `Hashing`_
76    cmake_path(`HASH`_ <path-var> <out-var>)
77
78Conventions
79^^^^^^^^^^^
80
81The following conventions are used in this command's documentation:
82
83``<path-var>``
84  Always the name of a variable.  For commands that expect a ``<path-var>``
85  as input, the variable must exist and it is expected to hold a single path.
86
87``<input>``
88  A string literal which may contain a path, path fragment, or multiple paths
89  with a special separator depending on the command.  See the description of
90  each command to see how this is interpreted.
91
92``<input>...``
93  Zero or more string literal arguments.
94
95``<out-var>``
96  The name of a variable into which the result of a command will be written.
97
98
99Path Structure And Terminology
100^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
101
102A path has the following structure (all components are optional, with some
103constraints):
104
105::
106
107  root-name root-directory-separator (item-name directory-separator)* filename
108
109``root-name``
110  Identifies the root on a filesystem with multiple roots (such as ``"C:"``
111  or ``"//myserver"``). It is optional.
112
113``root-directory-separator``
114  A directory separator that, if present, indicates that this path is
115  absolute.  If it is missing and the first element other than the
116  ``root-name`` is an ``item-name``, then the path is relative.
117
118``item-name``
119  A sequence of characters that aren't directory separators.  This name may
120  identify a file, a hard link, a symbolic link, or a directory.  Two special
121  cases are recognized:
122
123    * The item name consisting of a single dot character ``.`` is a
124      directory name that refers to the current directory.
125
126    * The item name consisting of two dot characters ``..`` is a
127      directory name that refers to the parent directory.
128
129  The ``(...)*`` pattern shown above is to indicate that there can be zero
130  or more item names, with multiple items separated by a
131  ``directory-separator``.  The ``()*`` characters are not part of the path.
132
133``directory-separator``
134  The only recognized directory separator is a forward slash character ``/``.
135  If this character is repeated, it is treated as a single directory
136  separator.  In other words, ``/usr///////lib`` is the same as ``/usr/lib``.
137
138.. _FILENAME_DEF:
139.. _EXTENSION_DEF:
140.. _STEM_DEF:
141
142``filename``
143  A path has a ``filename`` if it does not end with a ``directory-separator``.
144  The ``filename`` is effectively the last ``item-name`` of the path, so it
145  can also be a hard link, symbolic link or a directory.
146
147  A ``filename`` can have an *extension*.  By default, the extension is
148  defined as the sub-string beginning at the left-most period (including
149  the period) and until the end of the ``filename``.  In commands that
150  accept a ``LAST_ONLY`` keyword, ``LAST_ONLY`` changes the interpretation
151  to the sub-string beginning at the right-most period.
152
153  The following exceptions apply to the above interpretation:
154
155    * If the first character in the ``filename`` is a period, that period is
156      ignored (i.e. a ``filename`` like ``".profile"`` is treated as having
157      no extension).
158
159    * If the ``filename`` is either ``.`` or ``..``, it has no extension.
160
161  The *stem* is the part of the ``filename`` before the extension.
162
163Some commands refer to a ``root-path``.  This is the concatenation of
164``root-name`` and ``root-directory-separator``, either or both of which can
165be empty.  A ``relative-part`` refers to the full path with any ``root-path``
166removed.
167
168
169Creating A Path Variable
170^^^^^^^^^^^^^^^^^^^^^^^^
171
172While a path can be created with care using an ordinary :command:`set`
173command, it is recommended to use :ref:`cmake_path(SET) <cmake_path-SET>`
174instead, as it automatically converts the path to the required form where
175required.  The :ref:`cmake_path(APPEND) <APPEND>` subcommand may
176be another suitable alternative where a path needs to be constructed by
177joining fragments.  The following example compares the three methods for
178constructing the same path:
179
180.. code-block:: cmake
181
182  set(path1 "${CMAKE_CURRENT_SOURCE_DIR}/data")
183
184  cmake_path(SET path2 "${CMAKE_CURRENT_SOURCE_DIR}/data")
185
186  cmake_path(APPEND path3 "${CMAKE_CURRENT_SOURCE_DIR}" "data")
187
188`Modification`_ and `Generation`_ sub-commands can either store the result
189in-place, or in a separate variable named after an ``OUTPUT_VARIABLE``
190keyword.  All other sub-commands store the result in a mandatory ``<out-var>``
191variable.
192
193.. _Normalization:
194
195Normalization
196^^^^^^^^^^^^^
197
198Some sub-commands support *normalizing* a path.  The algorithm used to
199normalize a path is as follows:
200
2011. If the path is empty, stop (the normalized form of an empty path is
202   also an empty path).
2032. Replace each ``directory-separator``, which may consist of multiple
204   separators, with a single ``/`` (``/a///b  --> /a/b``).
2053. Remove each solitary period (``.``) and any immediately following
206   ``directory-separator`` (``/a/./b/. --> /a/b``).
2074. Remove each ``item-name`` (other than ``..``) that is immediately
208   followed by a ``directory-separator`` and a ``..``, along with any
209   immediately following ``directory-separator`` (``/a/b/../c --> a/c``).
2105. If there is a ``root-directory``, remove any ``..`` and any
211   ``directory-separators`` immediately following them.  The parent of the
212   root directory is treated as still the root directory (``/../a --> /a``).
2136. If the last ``item-name`` is ``..``, remove any trailing
214   ``directory-separator`` (``../ --> ..``).
2157. If the path is empty by this stage, add a ``dot`` (normal form of ``./``
216   is ``.``).
217
218
219Decomposition
220^^^^^^^^^^^^^
221
222.. _GET:
223.. _GET_ROOT_NAME:
224.. _GET_ROOT_DIRECTORY:
225.. _GET_ROOT_PATH:
226.. _GET_FILENAME:
227.. _GET_EXTENSION:
228.. _GET_STEM:
229.. _GET_RELATIVE_PART:
230.. _GET_PARENT_PATH:
231
232The following forms of the ``GET`` subcommand each retrieve a different
233component or group of components from a path.  See
234`Path Structure And Terminology`_ for the meaning of each path component.
235
236::
237
238  cmake_path(GET <path-var> ROOT_NAME <out-var>)
239  cmake_path(GET <path-var> ROOT_DIRECTORY <out-var>)
240  cmake_path(GET <path-var> ROOT_PATH <out-var>)
241  cmake_path(GET <path-var> FILENAME <out-var>)
242  cmake_path(GET <path-var> EXTENSION [LAST_ONLY] <out-var>)
243  cmake_path(GET <path-var> STEM [LAST_ONLY] <out-var>)
244  cmake_path(GET <path-var> RELATIVE_PART <out-var>)
245  cmake_path(GET <path-var> PARENT_PATH <out-var>)
246
247If a requested component is not present in the path, an empty string will be
248stored in ``<out-var>``.  For example, only Windows systems have the concept
249of a ``root-name``, so when the host machine is non-Windows, the ``ROOT_NAME``
250subcommand will always return an empty string.
251
252For ``PARENT_PATH``, if the `HAS_RELATIVE_PART`_ subcommand returns false,
253the result is a copy of ``<path-var>``.  Note that this implies that a root
254directory is considered to have a parent, with that parent being itself.
255Where `HAS_RELATIVE_PART`_ returns true, the result will essentially be
256``<path-var>`` with one less element.
257
258Root examples
259"""""""""""""
260
261.. code-block:: cmake
262
263  set(path "c:/a")
264
265  cmake_path(GET path ROOT_NAME rootName)
266  cmake_path(GET path ROOT_DIRECTORY rootDir)
267  cmake_path(GET path ROOT_PATH rootPath)
268
269  message("Root name is \"${rootName}\"")
270  message("Root directory is \"${rootDir}\"")
271  message("Root path is \"${rootPath}\"")
272
273::
274
275  Root name is "c:"
276  Root directory is "/"
277  Root path is "c:/"
278
279Filename examples
280"""""""""""""""""
281
282.. code-block:: cmake
283
284  set(path "/a/b")
285  cmake_path(GET path FILENAME filename)
286  message("First filename is \"${filename}\"")
287
288  # Trailing slash means filename is empty
289  set(path "/a/b/")
290  cmake_path(GET path FILENAME filename)
291  message("Second filename is \"${filename}\"")
292
293::
294
295  First filename is "b"
296  Second filename is ""
297
298Extension and stem examples
299"""""""""""""""""""""""""""
300
301.. code-block:: cmake
302
303  set(path "name.ext1.ext2")
304
305  cmake_path(GET path EXTENSION fullExt)
306  cmake_path(GET path STEM fullStem)
307  message("Full extension is \"${fullExt}\"")
308  message("Full stem is \"${fullStem}\"")
309
310  # Effect of LAST_ONLY
311  cmake_path(GET path EXTENSION LAST_ONLY lastExt)
312  cmake_path(GET path STEM LAST_ONLY lastStem)
313  message("Last extension is \"${lastExt}\"")
314  message("Last stem is \"${lastStem}\"")
315
316  # Special cases
317  set(dotPath "/a/.")
318  set(dotDotPath "/a/..")
319  set(someMorePath "/a/.some.more")
320  cmake_path(GET dotPath EXTENSION dotExt)
321  cmake_path(GET dotPath STEM dotStem)
322  cmake_path(GET dotDotPath EXTENSION dotDotExt)
323  cmake_path(GET dotDotPath STEM dotDotStem)
324  cmake_path(GET dotMorePath EXTENSION someMoreExt)
325  cmake_path(GET dotMorePath STEM someMoreStem)
326  message("Dot extension is \"${dotExt}\"")
327  message("Dot stem is \"${dotStem}\"")
328  message("Dot-dot extension is \"${dotDotExt}\"")
329  message("Dot-dot stem is \"${dotDotStem}\"")
330  message(".some.more extension is \"${someMoreExt}\"")
331  message(".some.more stem is \"${someMoreStem}\"")
332
333::
334
335  Full extension is ".ext1.ext2"
336  Full stem is "name"
337  Last extension is ".ext2"
338  Last stem is "name.ext1"
339  Dot extension is ""
340  Dot stem is "."
341  Dot-dot extension is ""
342  Dot-dot stem is ".."
343  .some.more extension is ".more"
344  .some.more stem is ".some"
345
346Relative part examples
347""""""""""""""""""""""
348
349.. code-block:: cmake
350
351  set(path "c:/a/b")
352  cmake_path(GET path RELATIVE_PART result)
353  message("Relative part is \"${result}\"")
354
355  set(path "c/d")
356  cmake_path(GET path RELATIVE_PART result)
357  message("Relative part is \"${result}\"")
358
359  set(path "/")
360  cmake_path(GET path RELATIVE_PART result)
361  message("Relative part is \"${result}\"")
362
363::
364
365  Relative part is "a/b"
366  Relative part is "c/d"
367  Relative part is ""
368
369Path traversal examples
370"""""""""""""""""""""""
371
372.. code-block:: cmake
373
374  set(path "c:/a/b")
375  cmake_path(GET path PARENT_PATH result)
376  message("Parent path is \"${result}\"")
377
378  set(path "c:/")
379  cmake_path(GET path PARENT_PATH result)
380  message("Parent path is \"${result}\"")
381
382::
383
384  Parent path is "c:/a"
385  Parent path is "c:/"
386
387
388Query
389^^^^^
390
391Each of the ``GET`` subcommands has a corresponding ``HAS_...``
392subcommand which can be used to discover whether a particular path
393component is present.  See `Path Structure And Terminology`_ for the
394meaning of each path component.
395
396.. _HAS_ROOT_NAME:
397.. _HAS_ROOT_DIRECTORY:
398.. _HAS_ROOT_PATH:
399.. _HAS_FILENAME:
400.. _HAS_EXTENSION:
401.. _HAS_STEM:
402.. _HAS_RELATIVE_PART:
403.. _HAS_PARENT_PATH:
404
405::
406
407  cmake_path(HAS_ROOT_NAME <path-var> <out-var>)
408  cmake_path(HAS_ROOT_DIRECTORY <path-var> <out-var>)
409  cmake_path(HAS_ROOT_PATH <path-var> <out-var>)
410  cmake_path(HAS_FILENAME <path-var> <out-var>)
411  cmake_path(HAS_EXTENSION <path-var> <out-var>)
412  cmake_path(HAS_STEM <path-var> <out-var>)
413  cmake_path(HAS_RELATIVE_PART <path-var> <out-var>)
414  cmake_path(HAS_PARENT_PATH <path-var> <out-var>)
415
416Each of the above follows the predictable pattern of setting ``<out-var>``
417to true if the path has the associated component, or false otherwise.
418Note the following special cases:
419
420* For ``HAS_ROOT_PATH``, a true result will only be returned if at least one
421  of ``root-name`` or ``root-directory`` is non-empty.
422
423* For ``HAS_PARENT_PATH``, the root directory is also considered to have a
424  parent, which will be itself.  The result is true except if the path
425  consists of just a :ref:`filename <FILENAME_DEF>`.
426
427.. _IS_ABSOLUTE:
428
429::
430
431  cmake_path(IS_ABSOLUTE <path-var> <out-var>)
432
433Sets ``<out-var>`` to true if ``<path-var>`` is absolute.  An absolute path
434is a path that unambiguously identifies the location of a file without
435reference to an additional starting location.  On Windows, this means the
436path must have both a ``root-name`` and a ``root-directory-separator`` to be
437considered absolute.  On other platforms, just a ``root-directory-separator``
438is sufficient.  Note that this means on Windows, ``IS_ABSOLUTE`` can be
439false while ``HAS_ROOT_DIRECTORY`` can be true.
440
441.. _IS_RELATIVE:
442
443::
444
445  cmake_path(IS_RELATIVE <path-var> <out-var>)
446
447This will store the opposite of ``IS_ABSOLUTE`` in ``<out-var>``.
448
449.. _IS_PREFIX:
450
451::
452
453  cmake_path(IS_PREFIX <path-var> <input> [NORMALIZE] <out-var>)
454
455Checks if ``<path-var>`` is the prefix of ``<input>``.
456
457When the ``NORMALIZE`` option is specified, ``<path-var>`` and ``<input>``
458are :ref:`normalized <Normalization>` before the check.
459
460.. code-block:: cmake
461
462  set(path "/a/b/c")
463  cmake_path(IS_PREFIX path "/a/b/c/d" result) # result = true
464  cmake_path(IS_PREFIX path "/a/b" result)     # result = false
465  cmake_path(IS_PREFIX path "/x/y/z" result)   # result = false
466
467  set(path "/a/b")
468  cmake_path(IS_PREFIX path "/a/c/../b" NORMALIZE result)   # result = true
469
470.. _COMPARE:
471
472::
473
474  cmake_path(COMPARE <input1> EQUAL <input2> <out-var>)
475  cmake_path(COMPARE <input1> NOT_EQUAL <input2> <out-var>)
476
477Compares the lexical representations of two paths provided as string literals.
478No normalization is performed on either path.  Equality is determined
479according to the following pseudo-code logic:
480
481::
482
483  if(NOT <input1>.root_name() STREQUAL <input2>.root_name())
484    return FALSE
485
486  if(<input1>.has_root_directory() XOR <input2>.has_root_directory())
487    return FALSE
488
489  Return FALSE if a relative portion of <input1> is not lexicographically
490  equal to the relative portion of <input2>. This comparison is performed path
491  component-wise. If all of the components compare equal, then return TRUE.
492
493.. note::
494  Unlike most other ``cmake_path()`` subcommands, the ``COMPARE`` subcommand
495  takes literal strings as input, not the names of variables.
496
497
498Modification
499^^^^^^^^^^^^
500
501.. _cmake_path-SET:
502
503::
504
505  cmake_path(SET <path-var> [NORMALIZE] <input>)
506
507Assign the ``<input>`` path to ``<path-var>``.  If ``<input>`` is a native
508path, it is converted into a cmake-style path with forward-slashes
509(``/``). On Windows, the long filename marker is taken into account.
510
511When the ``NORMALIZE`` option is specified, the path is :ref:`normalized
512<Normalization>` before the conversion.
513
514For example:
515
516.. code-block:: cmake
517
518  set(native_path "c:\\a\\b/..\\c")
519  cmake_path(SET path "${native_path}")
520  message("CMake path is \"${path}\"")
521
522  cmake_path(SET path NORMALIZE "${native_path}")
523  message("Normalized CMake path is \"${path}\"")
524
525Output::
526
527  CMake path is "c:/a/b/../c"
528  Normalized CMake path is "c:/a/c"
529
530.. _APPEND:
531
532::
533
534  cmake_path(APPEND <path-var> [<input>...] [OUTPUT_VARIABLE <out-var>])
535
536Append all the ``<input>`` arguments to the ``<path-var>`` using ``/`` as
537the ``directory-separator``.  Depending on the ``<input>``, the previous
538contents of ``<path-var>`` may be discarded.  For each ``<input>`` argument,
539the following algorithm (pseudo-code) applies:
540
541::
542
543  # <path> is the contents of <path-var>
544
545  if(<input>.is_absolute() OR
546     (<input>.has_root_name() AND
547      NOT <input>.root_name() STREQUAL <path>.root_name()))
548    replace <path> with <input>
549    return()
550  endif()
551
552  if(<input>.has_root_directory())
553    remove any root-directory and the entire relative path from <path>
554  elseif(<path>.has_filename() OR
555         (NOT <path-var>.has_root_directory() OR <path>.is_absolute()))
556    append directory-separator to <path>
557  endif()
558
559  append <input> omitting any root-name to <path>
560
561.. _APPEND_STRING:
562
563::
564
565  cmake_path(APPEND_STRING <path-var> [<input>...] [OUTPUT_VARIABLE <out-var>])
566
567Append all the ``<input>`` arguments to the ``<path-var>`` without adding any
568``directory-separator``.
569
570.. _REMOVE_FILENAME:
571
572::
573
574  cmake_path(REMOVE_FILENAME <path-var> [OUTPUT_VARIABLE <out-var>])
575
576Removes the :ref:`filename <FILENAME_DEF>` component (as returned by
577:ref:`GET ... FILENAME <GET_FILENAME>`) from ``<path-var>``.  After removal,
578any trailing ``directory-separator`` is left alone, if present.
579
580If ``OUTPUT_VARIABLE`` is not given, then after this function returns,
581`HAS_FILENAME`_ returns false for ``<path-var>``.
582
583For example:
584
585.. code-block:: cmake
586
587  set(path "/a/b")
588  cmake_path(REMOVE_FILENAME path)
589  message("First path is \"${path}\"")
590
591  # filename is now already empty, the following removes nothing
592  cmake_path(REMOVE_FILENAME path)
593  message("Second path is \"${result}\"")
594
595Output::
596
597  First path is "/a/"
598  Second path is "/a/"
599
600.. _REPLACE_FILENAME:
601
602::
603
604  cmake_path(REPLACE_FILENAME <path-var> <input> [OUTPUT_VARIABLE <out-var>])
605
606Replaces the :ref:`filename <FILENAME_DEF>` component from ``<path-var>``
607with ``<input>``.  If ``<path-var>`` has no filename component (i.e.
608`HAS_FILENAME`_ returns false), the path is unchanged.  The operation is
609equivalent to the following:
610
611.. code-block:: cmake
612
613  cmake_path(HAS_FILENAME path has_filename)
614  if(has_filename)
615    cmake_path(REMOVE_FILENAME path)
616    cmake_path(APPEND path input);
617  endif()
618
619.. _REMOVE_EXTENSION:
620
621::
622
623  cmake_path(REMOVE_EXTENSION <path-var> [LAST_ONLY]
624                                         [OUTPUT_VARIABLE <out-var>])
625
626Removes the :ref:`extension <EXTENSION_DEF>`, if any, from ``<path-var>``.
627
628.. _REPLACE_EXTENSION:
629
630::
631
632  cmake_path(REPLACE_EXTENSION <path-var> [LAST_ONLY] <input>
633                               [OUTPUT_VARIABLE <out-var>])
634
635Replaces the :ref:`extension <EXTENSION_DEF>` with ``<input>``.  Its effect
636is equivalent to the following:
637
638.. code-block:: cmake
639
640  cmake_path(REMOVE_EXTENSION path)
641  if(NOT "input" MATCHES "^\\.")
642    cmake_path(APPEND_STRING path ".")
643  endif()
644  cmake_path(APPEND_STRING path "input")
645
646
647Generation
648^^^^^^^^^^
649
650.. _NORMAL_PATH:
651
652::
653
654  cmake_path(NORMAL_PATH <path-var> [OUTPUT_VARIABLE <out-var>])
655
656Normalize ``<path-var>`` according the steps described in :ref:`Normalization`.
657
658.. _cmake_path-RELATIVE_PATH:
659.. _RELATIVE_PATH:
660
661::
662
663  cmake_path(RELATIVE_PATH <path-var> [BASE_DIRECTORY <input>]
664                                      [OUTPUT_VARIABLE <out-var>])
665
666Modifies ``<path-var>`` to make it relative to the ``BASE_DIRECTORY`` argument.
667If ``BASE_DIRECTORY`` is not specified, the default base directory will be
668:variable:`CMAKE_CURRENT_SOURCE_DIR`.
669
670For reference, the algorithm used to compute the relative path is the same
671as that used by C++
672`std::filesystem::path::lexically_relative
673<https://en.cppreference.com/w/cpp/filesystem/path/lexically_normal>`_.
674
675.. _ABSOLUTE_PATH:
676
677::
678
679  cmake_path(ABSOLUTE_PATH <path-var> [BASE_DIRECTORY <input>] [NORMALIZE]
680                                      [OUTPUT_VARIABLE <out-var>])
681
682If ``<path-var>`` is a relative path (`IS_RELATIVE`_ is true), it is evaluated
683relative to the given base directory specified by ``BASE_DIRECTORY`` option.
684If ``BASE_DIRECTORY`` is not specified, the default base directory will be
685:variable:`CMAKE_CURRENT_SOURCE_DIR`.
686
687When the ``NORMALIZE`` option is specified, the path is :ref:`normalized
688<Normalization>` after the path computation.
689
690Because ``cmake_path()`` does not access the filesystem, symbolic links are
691not resolved and any leading tilde is not expanded.  To compute a real path
692with symbolic links resolved and leading tildes expanded, use the
693:command:`file(REAL_PATH)` command instead.
694
695Native Conversion
696^^^^^^^^^^^^^^^^^
697
698For commands in this section, *native* refers to the host platform, not the
699target platform when cross-compiling.
700
701.. _cmake_path-NATIVE_PATH:
702.. _NATIVE_PATH:
703
704::
705
706  cmake_path(NATIVE_PATH <path-var> [NORMALIZE] <out-var>)
707
708Converts a cmake-style ``<path-var>`` into a native path with
709platform-specific slashes (``\`` on Windows hosts and ``/`` elsewhere).
710
711When the ``NORMALIZE`` option is specified, the path is :ref:`normalized
712<Normalization>` before the conversion.
713
714.. _CONVERT:
715.. _cmake_path-TO_CMAKE_PATH_LIST:
716.. _TO_CMAKE_PATH_LIST:
717
718::
719
720  cmake_path(CONVERT <input> TO_CMAKE_PATH_LIST <out-var> [NORMALIZE])
721
722Converts a native ``<input>`` path into a cmake-style path with forward
723slashes (``/``).  On Windows hosts, the long filename marker is taken into
724account.  The input can be a single path or a system search path like
725``$ENV{PATH}``.  A search path will be converted to a cmake-style list
726separated by ``;`` characters (on non-Windows platforms, this essentially
727means ``:`` separators are replaced with ``;``).  The result of the
728conversion is stored in the ``<out-var>`` variable.
729
730When the ``NORMALIZE`` option is specified, the path is :ref:`normalized
731<Normalization>` before the conversion.
732
733.. note::
734  Unlike most other ``cmake_path()`` subcommands, the ``CONVERT`` subcommand
735  takes a literal string as input, not the name of a variable.
736
737.. _cmake_path-TO_NATIVE_PATH_LIST:
738.. _TO_NATIVE_PATH_LIST:
739
740::
741
742  cmake_path(CONVERT <input> TO_NATIVE_PATH_LIST <out-var> [NORMALIZE])
743
744Converts a cmake-style ``<input>`` path into a native path with
745platform-specific slashes (``\`` on Windows hosts and ``/`` elsewhere).
746The input can be a single path or a cmake-style list.  A list will be
747converted into a native search path (``;``-separated on Windows,
748``:``-separated on other platforms).  The result of the conversion is
749stored in the ``<out-var>`` variable.
750
751When the ``NORMALIZE`` option is specified, the path is :ref:`normalized
752<Normalization>` before the conversion.
753
754.. note::
755  Unlike most other ``cmake_path()`` subcommands, the ``CONVERT`` subcommand
756  takes a literal string as input, not the name of a variable.
757
758For example:
759
760.. code-block:: cmake
761
762  set(paths "/a/b/c" "/x/y/z")
763  cmake_path(CONVERT "${paths}" TO_NATIVE_PATH_LIST native_paths)
764  message("Native path list is \"${native_paths}\"")
765
766Output on Windows::
767
768  Native path list is "\a\b\c;\x\y\z"
769
770Output on all other platforms::
771
772  Native path list is "/a/b/c:/x/y/z"
773
774Hashing
775^^^^^^^
776
777.. _HASH:
778
779::
780
781    cmake_path(HASH <path-var> <out-var>)
782
783Compute a hash value of ``<path-var>`` such that for two paths ``p1`` and
784``p2`` that compare equal (:ref:`COMPARE ... EQUAL <COMPARE>`), the hash
785value of ``p1`` is equal to the hash value of ``p2``.  The path is always
786:ref:`normalized <Normalization>` before the hash is computed.
787