Coverage Report

Created: 2026-09-14 06:43

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
71.9k
  {
44
71.9k
    return cmsys::SystemTools::LowerCase(std::string(s));
45
71.9k
  }
46
  static std::string LowerCase(char const* s)
47
71.9k
  {
48
71.9k
    return LowerCase(cm::string_view{ s });
49
71.9k
  }
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 std::string GetActualCaseForPath(std::string const& p);
430
431
  static cm::optional<std::string> GetEnvVar(std::string const& var);
432
  static std::vector<std::string> GetEnvPathNormalized(std::string const& var);
433
434
  static std::vector<std::string> SplitEnvPath(cm::string_view in);
435
  static std::vector<std::string> SplitEnvPathNormalized(cm::string_view in);
436
437
  /** Convert an input path to an absolute path with no '/..' components.
438
      Backslashes in the input path are converted to forward slashes.
439
      Relative paths are interpreted w.r.t. GetLogicalWorkingDirectory.
440
      This is similar to 'realpath', but preserves symlinks that are
441
      not erased by '../' components.
442
443
      On Windows and macOS, the on-disk capitalization is loaded for
444
      existing paths.  */
445
  static std::string ToNormalizedPathOnDisk(std::string p);
446
447
#ifndef CMAKE_BOOTSTRAP
448
  /** Remove an environment variable */
449
  static bool UnsetEnv(char const* value);
450
451
  /** Get the list of all environment variables */
452
  static std::vector<std::string> GetEnvironmentVariables();
453
454
  /** Helper class to save and restore the environment.
455
      Instantiate this class as an automatic variable on
456
      the stack. Its constructor saves a copy of the current
457
      environment and then its destructor restores the
458
      original environment. */
459
  class SaveRestoreEnvironment
460
  {
461
  public:
462
    SaveRestoreEnvironment();
463
    ~SaveRestoreEnvironment();
464
465
    SaveRestoreEnvironment(SaveRestoreEnvironment const&) = delete;
466
    SaveRestoreEnvironment& operator=(SaveRestoreEnvironment const&) = delete;
467
468
  private:
469
    std::vector<std::string> Env;
470
  };
471
#endif
472
473
  /** \class ScopedEnv
474
   * \brief An RAII class to temporarily set/unset an environment variable.
475
   *
476
   * The value passed to the constructor is put into the environment. This
477
   * variable is of the form "var=value" and the original value of the "var"
478
   * environment variable is saved. When the object is destroyed, the original
479
   * value for the environment variable is restored. If the variable didn't
480
   * exist, it will be unset.
481
   */
482
  class ScopedEnv
483
  {
484
  public:
485
    ScopedEnv(cm::string_view val);
486
    ~ScopedEnv();
487
488
    ScopedEnv(ScopedEnv const&) = delete;
489
    ScopedEnv& operator=(ScopedEnv const&) = delete;
490
491
  private:
492
    std::string Key;
493
    cm::optional<std::string> Original;
494
  };
495
496
  /** Setup the environment to enable VS 8 IDE output.  */
497
  static void EnableVSConsoleOutput();
498
499
  enum cmTarAction
500
  {
501
    TarActionCreate,
502
    TarActionList,
503
    TarActionExtract,
504
    TarActionNone
505
  };
506
507
  /** Create tar */
508
  enum cmTarCompression
509
  {
510
    TarCompressGZip,
511
    TarCompressBZip2,
512
    TarCompressLZMA,
513
    TarCompressXZ,
514
    TarCompressZstd,
515
    TarCompressPPMd,
516
    TarCompressAuto,
517
    TarCompressNone
518
  };
519
520
  enum class cmTarExtractTimestamps
521
  {
522
    Yes,
523
    No
524
  };
525
526
  static bool ListTar(std::string const& arFileName,
527
                      std::vector<std::string> const& files,
528
                      std::vector<std::string> const& excludeFiles,
529
                      std::string const& encoding, bool verbose);
530
  static bool CreateTar(std::string const& arFileName,
531
                        std::vector<std::string> const& files,
532
                        std::vector<std::string> const& excludeFiles,
533
                        std::string const& workingDirectory,
534
                        cmTarCompression compressType,
535
                        std::string const& encoding, bool verbose,
536
                        std::string const& mtime = std::string(),
537
                        std::string const& format = std::string(),
538
                        int compressionLevel = 0, int numThreads = 1);
539
  static bool ExtractTar(std::string const& arFileName,
540
                         std::vector<std::string> const& files,
541
                         std::vector<std::string> const& excludeFiles,
542
                         cmTarExtractTimestamps extractTimestamps,
543
                         std::string const& encoding, bool verbose);
544
545
  /** Random number generation.  */
546
  static unsigned int RandomSeed();
547
  static unsigned int RandomNumber();
548
549
  /**
550
   * Find an executable in the system PATH, with optional extra paths.
551
   * This wraps KWSys's FindProgram to add ToNormalizedPathOnDisk.
552
   */
553
  static std::string FindProgram(
554
    std::string const& name,
555
    std::vector<std::string> const& path = std::vector<std::string>());
556
557
  /** Find the directory containing CMake executables.  */
558
  static void FindCMakeResources(char const* argv0);
559
560
  /** Get the CMake resource paths, after FindCMakeResources.  */
561
  static std::string const& GetCTestCommand();
562
  static std::string const& GetCPackCommand();
563
  static std::string const& GetCMakeCommand();
564
  static std::string const& GetCMakeGUICommand();
565
  static std::string const& GetCMakeCursesCommand();
566
  static std::string const& GetCMClDepsCommand();
567
  static std::string const& GetCMakeRoot();
568
  static bool GetCMakeInBuildTree();
569
  static std::string const& GetHTMLDoc();
570
571
  /** Get the CMake config directory **/
572
  static cm::optional<std::string> GetSystemConfigDirectory();
573
  static cm::optional<std::string> GetCMakeConfigDirectory();
574
575
  static std::string const& GetLogicalWorkingDirectory();
576
577
  /** The logical working directory may contain symlinks but must not
578
      contain any '../' path components.  */
579
  static cmsys::Status SetLogicalWorkingDirectory(std::string const& lwd);
580
581
  /** Try to guess the soname of a shared library.  */
582
  static bool GuessLibrarySOName(std::string const& fullPath,
583
                                 std::string& soname);
584
585
  /** Try to guess the install name of a shared library.  */
586
  static bool GuessLibraryInstallName(std::string const& fullPath,
587
                                      std::string& soname);
588
589
  /** Try to change the RPATH in an ELF binary.  */
590
  static bool ChangeRPath(std::string const& file, std::string const& oldRPath,
591
                          std::string const& newRPath,
592
                          bool removeEnvironmentRPath,
593
                          std::string* emsg = nullptr,
594
                          bool* changed = nullptr);
595
596
  /** Try to set the RPATH in an ELF binary.  */
597
  static bool SetRPath(std::string const& file, std::string const& newRPath,
598
                       std::string* emsg = nullptr, bool* changed = nullptr);
599
600
  /** Try to remove the RPATH from an ELF binary.  */
601
  static bool RemoveRPath(std::string const& file, std::string* emsg = nullptr,
602
                          bool* removed = nullptr);
603
604
  /** Check whether the RPATH in an ELF binary contains the path
605
      given.  */
606
  static bool CheckRPath(std::string const& file, std::string const& newRPath);
607
608
  /** Remove a directory; repeat a few times in case of locked files.  */
609
  static cmsys::Status RepeatedRemoveDirectory(std::string const& dir);
610
611
  /** Encode a string as a URL.  */
612
  static std::string EncodeURL(std::string const& in,
613
                               bool escapeSlashes = true);
614
615
  enum class DirCase
616
  {
617
    Sensitive,
618
    Insensitive,
619
  };
620
621
  /** Returns nullopt when `dir` is not a valid directory */
622
  static cm::optional<DirCase> GetDirCase(std::string const& dir);
623
624
#ifdef _WIN32
625
  struct WindowsFileRetry
626
  {
627
    unsigned int Count;
628
    unsigned int Delay;
629
  };
630
  static WindowsFileRetry GetWindowsFileRetry();
631
  static WindowsFileRetry GetWindowsDirectoryRetry();
632
633
  struct WindowsVersion
634
  {
635
    unsigned int dwMajorVersion;
636
    unsigned int dwMinorVersion;
637
    unsigned int dwBuildNumber;
638
  };
639
  static WindowsVersion GetWindowsVersion();
640
641
  /** Attempt to get full path to COMSPEC, default "cmd.exe" */
642
  static std::string GetComspec();
643
#endif
644
645
  /** Get the real path for a given path, removing all symlinks.
646
      This variant of GetRealPath also works on Windows but will
647
      resolve subst drives too.  */
648
  static std::string GetRealPathResolvingWindowsSubst(
649
    std::string const& path, std::string* errorMessage = nullptr);
650
651
  /** Get the real path for a given path, removing all symlinks.  */
652
  static std::string GetRealPath(std::string const& path,
653
                                 std::string* errorMessage = nullptr);
654
655
  /** Perform one-time initialization of libuv.  */
656
  static void InitializeLibUV();
657
658
  /** Create a symbolic link if the platform supports it.  Returns whether
659
      creation succeeded. */
660
  static cmsys::Status CreateSymlink(std::string const& origName,
661
                                     std::string const& newName);
662
  static cmsys::Status CreateSymlinkQuietly(std::string const& origName,
663
                                            std::string const& newName);
664
665
  /** Create a hard link if the platform supports it.  Returns whether
666
      creation succeeded. */
667
  static cmsys::Status CreateLink(std::string const& origName,
668
                                  std::string const& newName);
669
  static cmsys::Status CreateLinkQuietly(std::string const& origName,
670
                                         std::string const& newName);
671
672
  /** Get the system name. */
673
  static cm::string_view GetSystemName();
674
675
  /** Get the system path separator character */
676
  static char GetSystemPathlistSeparator();
677
678
  /** Return subview of the full filename (i.e. file name without path) */
679
  static cm::string_view GetFilenameNameView(cm::string_view filename);
680
681
#if defined(_WIN32) || defined(__APPLE__)
682
  /** Read the on-disk spelling of the full filename's last component. */
683
  static cmsys::Status ReadNameOnDisk(std::string const& path,
684
                                      std::string& name);
685
#endif
686
687
  /**
688
   * Return subview of file extension of a full filename (dot included).
689
   * Warning: this is the shortest extension (for example: .gz of .tar.gz)
690
   */
691
  static cm::string_view GetFilenameLastExtensionView(
692
    cm::string_view filename);
693
694
private:
695
  static bool s_ForceUnixPaths;
696
  static bool s_RunCommandHideConsole;
697
  static bool s_ErrorOccurred;
698
  static bool s_FatalErrorOccurred;
699
  static bool s_DisableRunCommandOutput;
700
};