summaryrefslogtreecommitdiffstats
path: root/build2/in/init.cxx
blob: 25834568955dd152dcd7dd50924d7c0425329aea (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
// file      : build2/in/init.cxx -*- C++ -*-
// copyright : Copyright (c) 2014-2018 Code Synthesis Ltd
// license   : MIT; see accompanying LICENSE file

#include <build2/in/init.hxx>

#include <build2/scope.hxx>
#include <build2/context.hxx>
#include <build2/variable.hxx>
#include <build2/diagnostics.hxx>

#include <build2/in/rule.hxx>
#include <build2/in/target.hxx>

using namespace std;

namespace build2
{
  namespace in
  {
    static const rule rule_ ("in", "in");

    bool
    base_init (scope& rs,
               scope&,
               const location&,
               unique_ptr<module_base>&,
               bool first,
               bool,
               const variable_map&)
    {
      tracer trace ("in::base_init");
      l5 ([&]{trace << "for " << rs.out_path ();});

      assert (first);

      // Enter variables.
      //
      {
        auto& vp (var_pool.rw (rs));

        // Alternative variable substitution symbol with '$' being the
        // default.
        //
        vp.insert<string> ("in.symbol");

        // Substitution mode. Valid values are 'strict' (default) and 'lax'.
        // In the strict mode every substitution symbol is expected to start a
        // substitution with the double symbol (e.g., $$) serving as an escape
        // sequence.
        //
        // In the lax mode a pair of substitution symbols is only treated as a
        // substitution if what's between them looks like a build2 variable
        // name (i.e., doesn't contain spaces, etc). Everything else,
        // including unterminated substitution symbols, is copied as is. Note
        // also that in this mode the double symbol is not treated as an
        // escape sequence.
        //
        // The lax mode is mostly useful when trying to reuse existing .in
        // files, for example, from autoconf. Note, however, that the lax mode
        // is still stricter than the autoconf's semantics which also leaves
        // unknown substitutions as is.
        //
        vp.insert<string> ("in.substitution");
      }

      // Register target types.
      //
      rs.target_types.insert<in> ();

      return true;
    }

    bool
    init (scope& rs,
          scope& bs,
          const location& loc,
          unique_ptr<module_base>&,
          bool,
          bool,
          const variable_map&)
    {
      tracer trace ("in::init");
      l5 ([&]{trace << "for " << bs.out_path ();});

      // Load in.base.
      //
      if (!cast_false<bool> (rs["in.base.loaded"]))
        load_module (rs, rs, "in.base", loc);

      // Register rules.
      //
      {
        auto& r (bs.rules);

        // There are rules that are "derived" from this generic in rule in
        // order to provide extended preprocessing functionality (see the
        // version module for an example). To make sure they are tried first
        // we register for path_target, not file, but in rule::match() we only
        // match if the target is a file. A bit of a hack.
        //
        r.insert<path_target> (perform_update_id,   "in", rule_);
        r.insert<path_target> (perform_clean_id,    "in", rule_);
        r.insert<path_target> (configure_update_id, "in", rule_);
      }

      return true;
    }
  }
}