Coverage Report

Created: 2026-04-29 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmSystemTools.h
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file LICENSE.rst or https://cmake.org/licensing for details.  */
3
#pragma once
4
5
#include "cmConfigure.h" // IWYU pragma: keep
6
7
#if !defined(_WIN32)
8
#  include <sys/types.h>
9
#endif
10
11
#include <cstddef>
12
#include <functional>
13
#include <string>
14
#include <vector>
15
16
#include <cm/optional>
17
#include <cm/string_view>
18
19
#include <cm3p/uv.h>
20
21
#include "cmsys/Status.hxx"      // IWYU pragma: export
22
#include "cmsys/SystemTools.hxx" // IWYU pragma: export
23
24
#include "cmDuration.h"
25
#include "cmProcessOutput.h"
26
27
struct cmMessageMetadata;
28
29
/** \class cmSystemTools
30
 * \brief A collection of useful functions for CMake.
31
 *
32
 * cmSystemTools is a class that provides helper functions
33
 * for the CMake build system.
34
 */
35
class cmSystemTools : public cmsys::SystemTools
36
{
37
public:
38
  using Superclass = cmsys::SystemTools;
39
  using Encoding = cmProcessOutput::Encoding;
40
41
  /** Return a lower-case string.  */
42
  static std::string LowerCase(cm::string_view s)
43
0
  {
44
0
    return cmsys::SystemTools::LowerCase(std::string(s));
45
0
  }
46
  static std::string LowerCase(char const* s)
47
0
  {
48
0
    return LowerCase(cm::string_view{ s });
49
0
  }
50
  using cmsys::SystemTools::LowerCase;
51
52
  /** Return an upper-case string.  */
53
  static std::string UpperCase(cm::string_view s)
54
0
  {
55
0
    return cmsys::SystemTools::UpperCase(std::string(s));
56
0
  }
57
  static std::string UpperCase(char const* s)
58
0
  {
59
0
    return UpperCase(cm::string_view{ s });
60
0
  }
61
  using cmsys::SystemTools::UpperCase;
62
63
  /**
64
   * Look for and replace registry values in a string
65
   */
66
  static void ExpandRegistryValues(std::string& source,
67
                                   KeyWOW64 view = KeyWOW64_Default);
68
69
  /** Map help document name to file name.  */
70
  static std::string HelpFileName(cm::string_view);
71
72
  using MessageCallback =
73
    std::function<void(std::string const&, cmMessageMetadata const&)>;
74
  /**
75
   *  Set the function used by GUIs to display error messages
76
   *  Function gets passed: message as a const char*,
77
   *  title as a const char*.
78
   */
79
  static void SetMessageCallback(MessageCallback f);
80
81
  /**
82
   * Display an error message.
83
   */
84
  static void Error(std::string const& m);
85
86
  /**
87
   * Display a message.
88
   */
89
  static void Message(std::string const& m, char const* title = nullptr);
90
  static void Message(std::string const& m, cmMessageMetadata const& md);
91
92
  using OutputCallback = std::function<void(std::string const&)>;
93
94
  //! Send a string to stdout
95
  static void Stdout(std::string const& s);
96
  static void SetStdoutCallback(OutputCallback f);
97
98
  //! Send a string to stderr
99
  static void Stderr(std::string const& s);
100
  static void SetStderrCallback(OutputCallback f);
101
102
  using InterruptCallback = std::function<bool()>;
103
  static void SetInterruptCallback(InterruptCallback f);
104
  static bool GetInterruptFlag();
105
106
  //! Return true if there was an error at any point.
107
  static bool GetErrorOccurredFlag()
108
36
  {
109
36
    return cmSystemTools::s_ErrorOccurred ||
110
1
      cmSystemTools::s_FatalErrorOccurred || GetInterruptFlag();
111
36
  }
112
  //! If this is set to true, cmake stops processing commands.
113
  static void SetFatalErrorOccurred()
114
1
  {
115
1
    cmSystemTools::s_FatalErrorOccurred = true;
116
1
  }
117
1
  static void SetErrorOccurred() { cmSystemTools::s_ErrorOccurred = true; }
118
  //! Return true if there was an error at any point.
119
  static bool GetFatalErrorOccurred()
120
0
  {
121
0
    return cmSystemTools::s_FatalErrorOccurred || GetInterruptFlag();
122
0
  }
123
124
  //! Set the error occurred flag and fatal error back to false
125
  static void ResetErrorOccurredFlag()
126
0
  {
127
0
    cmSystemTools::s_FatalErrorOccurred = false;
128
0
    cmSystemTools::s_ErrorOccurred = false;
129
0
  }
130
131
  //! Return true if the path is a framework
132
  static bool IsPathToFramework(std::string const& path);
133
134
  //! Return true if the path is a xcframework
135
  static bool IsPathToXcFramework(std::string const& path);
136
137
  //! Return true if the path is a macOS non-framework shared library (aka
138
  //! .dylib)
139
  static bool IsPathToMacOSSharedLibrary(std::string const& path);
140
141
  static bool DoesFileExistWithExtensions(
142
    std::string const& name, std::vector<std::string> const& sourceExts);
143
144
  /**
145
   * Check if the given file exists in one of the parent directory of the
146
   * given file or directory and if it does, return the name of the file.
147
   * Toplevel specifies the top-most directory to where it will look.
148
   */
149
  static std::string FileExistsInParentDirectories(
150
    std::string const& fname, std::string const& directory,
151
    std::string const& toplevel);
152
153
  static void Glob(std::string const& directory, std::string const& regexp,
154
                   std::vector<std::string>& files);
155
  static void GlobDirs(std::string const& fullPath,
156
                       std::vector<std::string>& files);
157
158
  /**
159
   * Try to find a list of files that match the "simple" globbing
160
   * expression. At this point in time the globbing expressions have
161
   * to be in form: /directory/partial_file_name*. The * character has
162
   * to be at the end of the string and it does not support ?
163
   * []... The optional argument type specifies what kind of files you
164
   * want to find. 0 means all files, -1 means directories, 1 means
165
   * files only. This method returns true if search was successful.
166
   */
167
  static bool SimpleGlob(std::string const& glob,
168
                         std::vector<std::string>& files, int type = 0);
169
170
  enum class CopyInputRecent
171
  {
172
    No,
173
    Yes,
174
  };
175
  enum class CopyResult
176
  {
177
    Success,
178
    Failure,
179
  };
180
181
#if defined(_MSC_VER)
182
  /** Visual C++ does not define mode_t. */
183
  using mode_t = unsigned short;
184
#endif
185
186
  /**
187
   * Make a new temporary directory.  The path must end in "XXXXXX", and will
188
   * be modified to reflect the name of the directory created.  This function
189
   * is similar to POSIX mkdtemp (and is implemented using the same where that
190
   * function is available).
191
   *
192
   * This function can make a full path even if none of the directories existed
193
   * prior to calling this function.
194
   *
195
   * Note that this function may modify \p path even if it does not succeed.
196
   */
197
  static cmsys::Status MakeTempDirectory(char* path,
198
                                         mode_t const* mode = nullptr);
199
  static cmsys::Status MakeTempDirectory(std::string& path,
200
                                         mode_t const* mode = nullptr);
201
202
  /** Copy a file. */
203
  static CopyResult CopySingleFile(std::string const& oldname,
204
                                   std::string const& newname, CopyWhen when,
205
                                   CopyInputRecent inputRecent,
206
                                   std::string* err = nullptr);
207
208
  enum class Replace
209
  {
210
    Yes,
211
    No,
212
  };
213
  enum class RenameResult
214
  {
215
    Success,
216
    NoReplace,
217
    Failure,
218
  };
219
220
  /** Rename a file or directory within a single disk volume (atomic
221
      if possible).  */
222
  static bool RenameFile(std::string const& oldname,
223
                         std::string const& newname);
224
  static RenameResult RenameFile(std::string const& oldname,
225
                                 std::string const& newname, Replace replace,
226
                                 std::string* err = nullptr);
227
228
  //! Rename a file if contents are different, delete the source otherwise
229
  static cmsys::Status MoveFileIfDifferent(std::string const& source,
230
                                           std::string const& destination);
231
232
  /**
233
   * According to the CreateProcessW documentation:
234
   *
235
   *   To run a batch file, you must start the command interpreter; set
236
   *   lpApplicationName to cmd.exe and set lpCommandLine to the following
237
   *   arguments: /c plus the name of the batch file.
238
   *
239
   * Additionally, "cmd /c" does not always parse batch file names correctly
240
   * if they contain spaces, but using "cmd /c call" seems to work.
241
   *
242
   *  The function is noop on platforms different from the pure WIN32 one.
243
   */
244
  static void MaybePrependCmdExe(std::vector<std::string>& cmdLine);
245
246
  /**
247
   * Run a single executable command
248
   *
249
   * Output is controlled with outputflag. If outputflag is OUTPUT_NONE, no
250
   * user-viewable output from the program being run will be generated.
251
   * OUTPUT_MERGE is the legacy behavior where stdout and stderr are merged
252
   * into stdout.  OUTPUT_FORWARD copies the output to stdout/stderr as
253
   * it was received.  OUTPUT_PASSTHROUGH passes through the original handles.
254
   *
255
   * If timeout is specified, the command will be terminated after
256
   * timeout expires. Timeout is specified in seconds.
257
   *
258
   * Argument retVal should be a pointer to the location where the
259
   * exit code will be stored. If the retVal is not specified and
260
   * the program exits with a code other than 0, then the this
261
   * function will return false.
262
   *
263
   * If the command has spaces in the path the caller MUST call
264
   * cmSystemTools::ConvertToRunCommandPath on the command before passing
265
   * it into this function or it will not work.  The command must be correctly
266
   * escaped for this to with spaces.
267
   */
268
  enum OutputOption
269
  {
270
    OUTPUT_NONE = 0,
271
    OUTPUT_MERGE,
272
    OUTPUT_FORWARD,
273
    OUTPUT_PASSTHROUGH
274
  };
275
  static bool RunSingleCommand(std::string const& command,
276
                               std::string* captureStdOut = nullptr,
277
                               std::string* captureStdErr = nullptr,
278
                               int* retVal = nullptr,
279
                               char const* dir = nullptr,
280
                               OutputOption outputflag = OUTPUT_MERGE,
281
                               cmDuration timeout = cmDuration::zero());
282
  /**
283
   * In this version of RunSingleCommand, command[0] should be
284
   * the command to run, and each argument to the command should
285
   * be in command[1]...command[command.size()]
286
   */
287
  static bool RunSingleCommand(std::vector<std::string> const& command,
288
                               std::string* captureStdOut = nullptr,
289
                               std::string* captureStdErr = nullptr,
290
                               int* retVal = nullptr,
291
                               char const* dir = nullptr,
292
                               OutputOption outputflag = OUTPUT_MERGE,
293
                               cmDuration timeout = cmDuration::zero(),
294
                               Encoding encoding = cmProcessOutput::Auto,
295
                               std::vector<std::string> env = {});
296
297
  static std::string PrintSingleCommand(std::vector<std::string> const&);
298
299
  /**
300
   * Parse arguments out of a single string command
301
   */
302
  static std::vector<std::string> ParseArguments(std::string const& command);
303
304
  /** Parse arguments out of a windows command line string.  */
305
  static void ParseWindowsCommandLine(char const* command,
306
                                      std::vector<std::string>& args);
307
308
  /** Parse arguments out of a unix command line string.  */
309
  static void ParseUnixCommandLine(char const* command,
310
                                   std::vector<std::string>& args);
311
312
  /** Split a command-line string into the parsed command and the unparsed
313
      arguments.  Returns false on unfinished quoting or escaping.  */
314
  static bool SplitProgramFromArgs(std::string const& command,
315
                                   std::string& program, std::string& args);
316
317
  /**
318
   * Handle response file in an argument list and return a new argument list
319
   * **/
320
  static std::vector<std::string> HandleResponseFile(
321
    std::vector<std::string>::const_iterator argBeg,
322
    std::vector<std::string>::const_iterator argEnd);
323
324
  static std::size_t CalculateCommandLineLengthLimit();
325
326
0
  static void DisableRunCommandOutput() { s_DisableRunCommandOutput = true; }
327
0
  static void EnableRunCommandOutput() { s_DisableRunCommandOutput = false; }
328
0
  static bool GetRunCommandOutput() { return s_DisableRunCommandOutput; }
329
330
  enum CompareOp
331
  {
332
    OP_EQUAL = 1,
333
    OP_LESS = 2,
334
    OP_GREATER = 4,
335
    OP_LESS_EQUAL = OP_LESS | OP_EQUAL,
336
    OP_GREATER_EQUAL = OP_GREATER | OP_EQUAL
337
  };
338
339
  /**
340
   * Compare versions
341
   */
342
  static bool VersionCompare(CompareOp op, std::string const& lhs,
343
                             std::string const& rhs);
344
  static bool VersionCompare(CompareOp op, std::string const& lhs,
345
                             char const rhs[]);
346
  static bool VersionCompareEqual(std::string const& lhs,
347
                                  std::string const& rhs);
348
  static bool VersionCompareGreater(std::string const& lhs,
349
                                    std::string const& rhs);
350
  static bool VersionCompareGreaterEq(std::string const& lhs,
351
                                      std::string const& rhs);
352
353
  /**
354
   * Compare two ASCII strings using natural versioning order.
355
   * Non-numerical characters are compared directly.
356
   * Numerical characters are first globbed such that, e.g.
357
   * `test000 < test01 < test0 < test1 < test10`.
358
   * Return a value less than, equal to, or greater than zero if lhs
359
   * precedes, equals, or succeeds rhs in the defined ordering.
360
   */
361
  static int strverscmp(std::string const& lhs, std::string const& rhs);
362
363
  /** Windows if this is true, the CreateProcess in RunCommand will
364
   *  not show new console windows when running programs.
365
   */
366
0
  static void SetRunCommandHideConsole(bool v) { s_RunCommandHideConsole = v; }
367
0
  static bool GetRunCommandHideConsole() { return s_RunCommandHideConsole; }
368
  /** Call cmSystemTools::Error with the message m, plus the
369
   * result of strerror(errno)
370
   */
371
  static void ReportLastSystemError(char const* m);
372
373
  enum class WaitForLineResult
374
  {
375
    None,
376
    STDOUT,
377
    STDERR,
378
  };
379
380
  /** a general output handler for libuv  */
381
  static WaitForLineResult WaitForLine(uv_loop_t* loop, uv_stream_t* outPipe,
382
                                       uv_stream_t* errPipe, std::string& line,
383
                                       std::vector<char>& out,
384
                                       std::vector<char>& err);
385
386
0
  static void SetForceUnixPaths(bool v) { s_ForceUnixPaths = v; }
387
0
  static bool GetForceUnixPaths() { return s_ForceUnixPaths; }
388
389
  // ConvertToOutputPath use s_ForceUnixPaths
390
  static std::string ConvertToOutputPath(std::string const& path);
391
  static void ConvertToOutputSlashes(std::string& path);
392
393
  // ConvertToRunCommandPath does not use s_ForceUnixPaths and should
394
  // be used when RunCommand is called from cmake, because the
395
  // running cmake needs paths to be in its format
396
  static std::string ConvertToRunCommandPath(std::string const& path);
397
398
  /**
399
   * For windows computes the long path for the given path,
400
   * For Unix, it is a noop
401
   */
402
  static void ConvertToLongPath(std::string& path);
403
404
  /** compute the relative path from local to remote.  local must
405
      be a directory.  remote can be a file or a directory.
406
      Both remote and local must be full paths.  Basically, if
407
      you are in directory local and you want to access the file in remote
408
      what is the relative path to do that.  For example:
409
      /a/b/c/d to /a/b/c1/d1 -> ../../c1/d1
410
      from /usr/src to /usr/src/test/blah/foo.cpp -> test/blah/foo.cpp
411
  */
412
  static std::string RelativePath(std::string const& local,
413
                                  std::string const& remote);
414
415
  /**
416
   * Convert the given remote path to a relative path with respect to
417
   * the given local path.  Both paths must use forward slashes and not
418
   * already be escaped or quoted.
419
   */
420
  static std::string ForceToRelativePath(std::string const& local_path,
421
                                         std::string const& remote_path);
422
423
  /**
424
   * Express the 'in' path relative to 'top' if it does not start in '../'.
425
   */
426
  static std::string RelativeIfUnder(std::string const& top,
427
                                     std::string const& in);
428
429
  static cm::optional<std::string> GetEnvVar(std::string const& var);
430
  static std::vector<std::string> GetEnvPathNormalized(std::string const& var);
431
432
  static std::vector<std::string> SplitEnvPath(cm::string_view in);
433
  static std::vector<std::string> SplitEnvPathNormalized(cm::string_view in);
434
435
  /** Convert an input path to an absolute path with no '/..' components.
436
      Backslashes in the input path are converted to forward slashes.
437
      Relative paths are interpreted w.r.t. GetLogicalWorkingDirectory.
438
      This is similar to 'realpath', but preserves symlinks that are
439
      not erased by '../' components.
440
441
      On Windows and macOS, the on-disk capitalization is loaded for
442
      existing paths.  */
443
  static std::string ToNormalizedPathOnDisk(std::string p);
444
445
#ifndef CMAKE_BOOTSTRAP
446
  /** Remove an environment variable */
447
  static bool UnsetEnv(char const* value);
448
449
  /** Get the list of all environment variables */
450
  static std::vector<std::string> GetEnvironmentVariables();
451
452
  /** Helper class to save and restore the environment.
453
      Instantiate this class as an automatic variable on
454
      the stack. Its constructor saves a copy of the current
455
      environment and then its destructor restores the
456
      original environment. */
457
  class SaveRestoreEnvironment
458
  {
459
  public:
460
    SaveRestoreEnvironment();
461
    ~SaveRestoreEnvironment();
462
463
    SaveRestoreEnvironment(SaveRestoreEnvironment const&) = delete;
464
    SaveRestoreEnvironment& operator=(SaveRestoreEnvironment const&) = delete;
465
466
  private:
467
    std::vector<std::string> Env;
468
  };
469
#endif
470
471
  /** \class ScopedEnv
472
   * \brief An RAII class to temporarily set/unset an environment variable.
473
   *
474
   * The value passed to the constructor is put into the environment. This
475
   * variable is of the form "var=value" and the original value of the "var"
476
   * environment variable is saved. When the object is destroyed, the original
477
   * value for the environment variable is restored. If the variable didn't
478
   * exist, it will be unset.
479
   */
480
  class ScopedEnv
481
  {
482
  public:
483
    ScopedEnv(cm::string_view val);
484
    ~ScopedEnv();
485
486
    ScopedEnv(ScopedEnv const&) = delete;
487
    ScopedEnv& operator=(ScopedEnv const&) = delete;
488
489
  private:
490
    std::string Key;
491
    cm::optional<std::string> Original;
492
  };
493
494
  /** Setup the environment to enable VS 8 IDE output.  */
495
  static void EnableVSConsoleOutput();
496
497
  enum cmTarAction
498
  {
499
    TarActionCreate,
500
    TarActionList,
501
    TarActionExtract,
502
    TarActionNone
503
  };
504
505
  /** Create tar */
506
  enum cmTarCompression
507
  {
508
    TarCompressGZip,
509
    TarCompressBZip2,
510
    TarCompressLZMA,
511
    TarCompressXZ,
512
    TarCompressZstd,
513
    TarCompressPPMd,
514
    TarCompressAuto,
515
    TarCompressNone
516
  };
517
518
  enum class cmTarExtractTimestamps
519
  {
520
    Yes,
521
    No
522
  };
523
524
  static bool ListTar(std::string const& arFileName,
525
                      std::vector<std::string> const& files,
526
                      std::string const& encoding, bool verbose);
527
  static bool CreateTar(std::string const& arFileName,
528
                        std::vector<std::string> const& files,
529
                        std::string const& workingDirectory,
530
                        cmTarCompression compressType,
531
                        std::string const& encoding, bool verbose,
532
                        std::string const& mtime = std::string(),
533
                        std::string const& format = std::string(),
534
                        int compressionLevel = 0, int numThreads = 1);
535
  static bool ExtractTar(std::string const& arFileName,
536
                         std::vector<std::string> const& files,
537
                         cmTarExtractTimestamps extractTimestamps,
538
                         std::string const& encoding, bool verbose);
539
540
  /** Random number generation.  */
541
  static unsigned int RandomSeed();
542
  static unsigned int RandomNumber();
543
544
  /**
545
   * Find an executable in the system PATH, with optional extra paths.
546
   * This wraps KWSys's FindProgram to add ToNormalizedPathOnDisk.
547
   */
548
  static std::string FindProgram(
549
    std::string const& name,
550
    std::vector<std::string> const& path = std::vector<std::string>());
551
552
  /** Find the directory containing CMake executables.  */
553
  static void FindCMakeResources(char const* argv0);
554
555
  /** Get the CMake resource paths, after FindCMakeResources.  */
556
  static std::string const& GetCTestCommand();
557
  static std::string const& GetCPackCommand();
558
  static std::string const& GetCMakeCommand();
559
  static std::string const& GetCMakeGUICommand();
560
  static std::string const& GetCMakeCursesCommand();
561
  static std::string const& GetCMClDepsCommand();
562
  static std::string const& GetCMakeRoot();
563
  static std::string const& GetHTMLDoc();
564
565
  /** Get the CMake config directory **/
566
  static cm::optional<std::string> GetSystemConfigDirectory();
567
  static cm::optional<std::string> GetCMakeConfigDirectory();
568
569
  static std::string const& GetLogicalWorkingDirectory();
570
571
  /** The logical working directory may contain symlinks but must not
572
      contain any '../' path components.  */
573
  static cmsys::Status SetLogicalWorkingDirectory(std::string const& lwd);
574
575
  /** Try to guess the soname of a shared library.  */
576
  static bool GuessLibrarySOName(std::string const& fullPath,
577
                                 std::string& soname);
578
579
  /** Try to guess the install name of a shared library.  */
580
  static bool GuessLibraryInstallName(std::string const& fullPath,
581
                                      std::string& soname);
582
583
  /** Try to change the RPATH in an ELF binary.  */
584
  static bool ChangeRPath(std::string const& file, std::string const& oldRPath,
585
                          std::string const& newRPath,
586
                          bool removeEnvironmentRPath,
587
                          std::string* emsg = nullptr,
588
                          bool* changed = nullptr);
589
590
  /** Try to set the RPATH in an ELF binary.  */
591
  static bool SetRPath(std::string const& file, std::string const& newRPath,
592
                       std::string* emsg = nullptr, bool* changed = nullptr);
593
594
  /** Try to remove the RPATH from an ELF binary.  */
595
  static bool RemoveRPath(std::string const& file, std::string* emsg = nullptr,
596
                          bool* removed = nullptr);
597
598
  /** Check whether the RPATH in an ELF binary contains the path
599
      given.  */
600
  static bool CheckRPath(std::string const& file, std::string const& newRPath);
601
602
  /** Remove a directory; repeat a few times in case of locked files.  */
603
  static cmsys::Status RepeatedRemoveDirectory(std::string const& dir);
604
605
  /** Encode a string as a URL.  */
606
  static std::string EncodeURL(std::string const& in,
607
                               bool escapeSlashes = true);
608
609
  enum class DirCase
610
  {
611
    Sensitive,
612
    Insensitive,
613
  };
614
615
  /** Returns nullopt when `dir` is not a valid directory */
616
  static cm::optional<DirCase> GetDirCase(std::string const& dir);
617
618
#ifdef _WIN32
619
  struct WindowsFileRetry
620
  {
621
    unsigned int Count;
622
    unsigned int Delay;
623
  };
624
  static WindowsFileRetry GetWindowsFileRetry();
625
  static WindowsFileRetry GetWindowsDirectoryRetry();
626
627
  struct WindowsVersion
628
  {
629
    unsigned int dwMajorVersion;
630
    unsigned int dwMinorVersion;
631
    unsigned int dwBuildNumber;
632
  };
633
  static WindowsVersion GetWindowsVersion();
634
635
  /** Attempt to get full path to COMSPEC, default "cmd.exe" */
636
  static std::string GetComspec();
637
#endif
638
639
  /** Get the real path for a given path, removing all symlinks.
640
      This variant of GetRealPath also works on Windows but will
641
      resolve subst drives too.  */
642
  static std::string GetRealPathResolvingWindowsSubst(
643
    std::string const& path, std::string* errorMessage = nullptr);
644
645
  /** Get the real path for a given path, removing all symlinks.  */
646
  static std::string GetRealPath(std::string const& path,
647
                                 std::string* errorMessage = nullptr);
648
649
  /** Perform one-time initialization of libuv.  */
650
  static void InitializeLibUV();
651
652
  /** Create a symbolic link if the platform supports it.  Returns whether
653
      creation succeeded. */
654
  static cmsys::Status CreateSymlink(std::string const& origName,
655
                                     std::string const& newName);
656
  static cmsys::Status CreateSymlinkQuietly(std::string const& origName,
657
                                            std::string const& newName);
658
659
  /** Create a hard link if the platform supports it.  Returns whether
660
      creation succeeded. */
661
  static cmsys::Status CreateLink(std::string const& origName,
662
                                  std::string const& newName);
663
  static cmsys::Status CreateLinkQuietly(std::string const& origName,
664
                                         std::string const& newName);
665
666
  /** Get the system name. */
667
  static cm::string_view GetSystemName();
668
669
  /** Get the system path separator character */
670
  static char GetSystemPathlistSeparator();
671
672
  /** Return subview of the full filename (i.e. file name without path) */
673
  static cm::string_view GetFilenameNameView(cm::string_view filename);
674
675
  /**
676
   * Return subview of file extension of a full filename (dot included).
677
   * Warning: this is the shortest extension (for example: .gz of .tar.gz)
678
   */
679
  static cm::string_view GetFilenameLastExtensionView(
680
    cm::string_view filename);
681
682
private:
683
  static bool s_ForceUnixPaths;
684
  static bool s_RunCommandHideConsole;
685
  static bool s_ErrorOccurred;
686
  static bool s_FatalErrorOccurred;
687
  static bool s_DisableRunCommandOutput;
688
};