summaryrefslogtreecommitdiffstats
path: root/Source/cmOutputConverter.h
blob: 0ee7afb553fd1bab9f7c7cffab1dc920bc5adf34 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#pragma once

#include "cmConfigure.h" // IWYU pragma: keep

#include <string>

#include <cm/string_view>

#include "cmStateSnapshot.h"

class cmState;

class cmOutputConverter
{
public:
  cmOutputConverter(cmStateSnapshot const& snapshot);
  virtual ~cmOutputConverter() = default;

  /**
   * Convert the given remote path to a relative path with respect to
   * one of our common work directories.  The path must use forward
   * slashes and not already be escaped or quoted.
   * The conversion is skipped if the paths are not both in the source
   * or both in the binary tree.
   */
  std::string MaybeRelativeToTopBinDir(std::string const& path) const;
  std::string MaybeRelativeToCurBinDir(std::string const& path) const;

  /**
   * The effective working directory can be different for each generator.
   * By default, equivalent to the current binary directory.
   */
  virtual std::string MaybeRelativeToWorkDir(std::string const& path) const
  {
    return this->MaybeRelativeToCurBinDir(path);
  }

  std::string const& GetRelativePathTopSource() const;
  std::string const& GetRelativePathTopBinary() const;
  void SetRelativePathTop(std::string const& topSource,
                          std::string const& topBinary);

  enum OutputFormat
  {
    SHELL,
    NINJAMULTI,
    RESPONSE
  };
  std::string ConvertToOutputFormat(cm::string_view source,
                                    OutputFormat output,
                                    bool useWatcomQuote = false) const;
  std::string ConvertDirectorySeparatorsForShell(cm::string_view source) const;

  //! for existing files convert to output path and short path if spaces
  std::string ConvertToOutputForExisting(const std::string& remote,
                                         OutputFormat format = SHELL,
                                         bool useWatcomQuote = false) const;

  void SetLinkScriptShell(bool linkScriptShell);

  /**
   * Flags to pass to Shell_GetArgument.  These modify the generated
   * quoting and escape sequences to work under alternative
   * environments.
   */
  enum Shell_Flag_e
  {
    /** The target shell is in a makefile.  */
    Shell_Flag_Make = (1 << 0),

    /** The target shell is in a VS project file.  Do not use with
        Shell_Flag_Make.  */
    Shell_Flag_VSIDE = (1 << 1),

    /** In a windows shell the argument is being passed to "echo".  */
    Shell_Flag_EchoWindows = (1 << 2),

    /** The target shell is in a Watcom WMake makefile.  */
    Shell_Flag_WatcomWMake = (1 << 3),

    /** The target shell is in a MinGW Make makefile.  */
    Shell_Flag_MinGWMake = (1 << 4),

    /** The target shell is in a NMake makefile.  */
    Shell_Flag_NMake = (1 << 5),

    /** Make variable reference syntax $(MAKEVAR) should not be escaped
        to allow a build tool to replace it.  Replacement values
        containing spaces, quotes, backslashes, or other
        non-alphanumeric characters that have significance to some makes
        or shells produce undefined behavior.  */
    Shell_Flag_AllowMakeVariables = (1 << 6),

    /** The target shell quoting uses extra single Quotes for Watcom tools.  */
    Shell_Flag_WatcomQuote = (1 << 7),

    Shell_Flag_IsUnix = (1 << 8),

    Shell_Flag_UnescapeNinjaConfiguration = (1 << 9),

    Shell_Flag_IsResponse = (1 << 10)
  };

  std::string EscapeForShell(cm::string_view str, bool makeVars = false,
                             bool forEcho = false, bool useWatcomQuote = false,
                             bool unescapeNinjaConfiguration = false,
                             bool forResponse = false) const;
  static std::string EscapeForShell(cm::string_view str, int flags);

  enum class WrapQuotes
  {
    Wrap,
    NoWrap,
  };
  static std::string EscapeForCMake(cm::string_view str,
                                    WrapQuotes wrapQuotes = WrapQuotes::Wrap);

  /** Compute an escaped version of the given argument for use in a
      windows shell.  */
  static std::string EscapeWindowsShellArgument(cm::string_view arg,
                                                int shell_flags);

  enum FortranFormat
  {
    FortranFormatNone,
    FortranFormatFixed,
    FortranFormatFree
  };
  static FortranFormat GetFortranFormat(cm::string_view value);

  enum class FortranPreprocess
  {
    Unset,
    NotNeeded,
    Needed
  };
  static FortranPreprocess GetFortranPreprocess(cm::string_view value);

protected:
  cmStateSnapshot StateSnapshot;

private:
  cmState* GetState() const;

  static bool Shell_CharNeedsQuotes(char c, int flags);
  static cm::string_view::iterator Shell_SkipMakeVariables(
    cm::string_view::iterator begin, cm::string_view::iterator end);
  static bool Shell_ArgumentNeedsQuotes(cm::string_view in, int flags);
  static std::string Shell_GetArgument(cm::string_view in, int flags);

  bool LinkScriptShell = false;

  // The top-most directories for relative path conversion.  Both the
  // source and destination location of a relative path conversion
  // must be underneath one of these directories (both under source or
  // both under binary) in order for the relative path to be evaluated
  // safely by the build tools.
  std::string RelativePathTopSource;
  std::string RelativePathTopBinary;
  enum class TopRelation
  {
    Separate,
    BinInSrc,
    SrcInBin,
    InSource,
  };
  TopRelation RelativePathTopRelation = TopRelation::Separate;
  void ComputeRelativePathTopSource();
  void ComputeRelativePathTopBinary();
  void ComputeRelativePathTopRelation();
  std::string MaybeRelativeTo(std::string const& local_path,
                              std::string const& remote_path) const;
};