aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/build/script/script.hxx
blob: f4d70acf0a48d3b425f44c22cea6fa5fda5c5f0e (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
176
177
178
179
180
// file      : libbuild2/build/script/script.hxx -*- C++ -*-
// license   : MIT; see accompanying LICENSE file

#ifndef LIBBUILD2_BUILD_SCRIPT_SCRIPT_HXX
#define LIBBUILD2_BUILD_SCRIPT_SCRIPT_HXX

#include <libbuild2/types.hxx>
#include <libbuild2/forward.hxx>
#include <libbuild2/utility.hxx>

#include <libbuild2/variable.hxx>
#include <libbuild2/filesystem.hxx> // auto_rmdir

#include <libbuild2/script/script.hxx>

namespace build2
{
  namespace build
  {
    namespace script
    {
      using build2::script::line;
      using build2::script::lines;
      using build2::script::line_type;
      using build2::script::redirect;
      using build2::script::redirect_type;
      using build2::script::expr_term;
      using build2::script::command_expr;

      // Notes:
      //
      // - Once parsed, the script can be executed in multiple threads with
      //   the state (variable values, etc) maintained in the environment.
      //
      // - The default script command redirects semantics is 'none' for stdin,
      //   'merge' into stderr for stdout, and 'pass' for stderr.
      //
      class script
      {
      public:
        using lines_type = build::script::lines;

        // Note that the variables are not pre-entered into a pool during the
        // parsing phase, so the line variable pointers are NULL.
        //
        lines_type lines;

        // Referenced ordinary (non-special) variables.
        //
        // Used for the script semantics change tracking. The variable list is
        // filled during the pre-parsing phase and is checked against during
        // the execution phase. If during execution some non-script-local
        // variable is not found in the list (may happen for a computed name),
        // then the execution fails since the script semantics may not be
        // properly tracked (the variable value change will not trigger the
        // target rebuild).
        //
        small_vector<string, 2> vars; // 2 for command and options.

        // True if script references the $~ special variable.
        //
        bool temp_dir = false;

        // Command name for low-verbosity diagnostics and custom low-verbosity
        // diagnostics line. Note: cannot be both (see the script parser for
        // details).
        //
        optional<string> diag_name;
        optional<line>   diag_line;

        // The script's custom dependency change tracking lines (see the
        // script parser for details).
        //
        bool       depdb_clear;
        lines_type depdb_lines;

        location start_loc;
        location end_loc;
      };

      class environment: public build2::script::environment
      {
      public:
        using target_type = build2::target;

        environment (action, const target_type&, bool temp_dir);

        environment (environment&&) = delete;
        environment (const environment&) = delete;
        environment& operator= (environment&&) = delete;
        environment& operator= (const environment&) = delete;

      public:
        // Primary target this environment is for.
        //
        const target_type& target;

        // Script-local variable pool and map.
        //
        // Note that it may be tempting to reuse the rule-specific variables
        // for this but they should no be modified during execution (i.e.,
        // they are for intra-rule communication; perhaps we could have a
        // special builtin that sets such variables during match).
        //
        // Note also that if we lookup the variable by passing name as a
        // string, then it will be looked up in the wrong pool.
        //
        variable_pool var_pool;
        variable_map vars;

        // Temporary directory for the script run.
        //
        // Currently this directory is removed regardless of the script
        // execution success or failure. Later, to help with troubleshooting,
        // we may invent an option that suppresses the removal of temporary
        // files in general.
        //
        // This directory is available to the user via the $~ special
        // variable. Note, however, that the following filesystem entry
        // prefixes are reserved:
        //
        // stdin*
        // stdout*
        // stderr*
        //
        auto_rmdir temp_dir;

        virtual void
        set_variable (string&& name,
                      names&&,
                      const string& attrs,
                      const location&) override;

        virtual void
        create_temp_dir () override;

        // Variables.
        //
      public:
        // Lookup the variable starting from this environment, then the
        // primary target, and then outer buildfile scopes.
        //
        // Note that we currently skip rule-specific variables since the rule
        // that runs this script doesn't set any.
        //
        using lookup_type = build2::lookup;

        lookup_type
        lookup (const variable&) const;

        lookup_type
        lookup (const string&) const;

        // As above but only look for buildfile variables.
        //
        lookup_type
        lookup_in_buildfile (const string&) const;

        // Return a value suitable for assignment. If the variable does not
        // exist in this environment's variable map, then a new one with the
        // NULL value is added and returned. Otherwise the existing value is
        // returned.
        //
        value&
        assign (const variable& var) {return vars.assign (var);}

        // Return a value suitable for append/prepend. If the variable does
        // not exist in this environment's variable map, then outer scopes are
        // searched for the same variable. If found then a new variable with
        // the found value is added to the environment and returned. Otherwise
        // this function proceeds as assign() above.
        //
        value&
        append (const variable&);
      };
    }
  }
}

#endif // LIBBUILD2_BUILD_SCRIPT_SCRIPT_HXX