aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/config/module.hxx
blob: 96220ac894b78ec9cef6c2218413163f3cc9b2b1 (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
// file      : libbuild2/config/module.hxx -*- C++ -*-
// license   : MIT; see accompanying LICENSE file

#ifndef LIBBUILD2_CONFIG_MODULE_HXX
#define LIBBUILD2_CONFIG_MODULE_HXX

#include <map>

#include <libbutl/prefix-map.mxx>

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

#include <libbuild2/scope.hxx>
#include <libbuild2/module.hxx>
#include <libbuild2/variable.hxx>

#include <libbuild2/config/utility.hxx>

namespace build2
{
  namespace config
  {
    // An ordered list of build system modules each with an ordered list of
    // config.* variables and their "save flags" (see save_variable()) that
    // are used (as opposed to just being specified) in this configuration.
    // Populated by the config utility functions (required(), optional()) and
    // saved in the order populated.
    //
    struct saved_variable
    {
      reference_wrapper<const variable> var;
      uint64_t flags;
    };

    struct saved_variables: vector<saved_variable>
    {
      // Normally each module only have a handful of config variables and we
      // only do this during configuration so for now we do linear search
      // instead of adding a map.
      //
      const_iterator
      find (const variable& var) const
      {
        return std::find_if (
          begin (),
          end (),
          [&var] (const saved_variable& v) {return var == v.var;});
      }
    };

    struct saved_modules: butl::prefix_map<string, saved_variables, '.'>
    {
      // Priority order with INT32_MIN being the highest. Modules with the
      // same priority are saved in the order inserted.
      //
      std::multimap<std::int32_t, const_iterator> order;

      pair<iterator, bool>
      insert (string name, int prio = 0)
      {
        auto p (emplace (move (name), saved_variables ()));

        if (p.second)
          order.emplace (prio, p.first);

        return p;
      }
    };

    struct module: build2::module
    {
      config::saved_modules saved_modules;

      // Return true if variable/module were newly inserted.
      //
      bool
      save_variable (const variable&, uint64_t flags = 0);

      static void
      save_variable (scope&, const variable&, uint64_t);

      bool
      save_module (const char* name, int prio = 0);

      static void
      save_module (scope&, const char*, int);

      // Return true if the variable is already saved.
      //
      bool
      saved (const variable& var)
      {
        auto i (saved_modules.find_sup (var.name));
        return i != saved_modules.end () &&
          i->second.find (var) != i->second.end ();
      }

      // Configure/disfigure hooks.
      //
      static bool
      configure_post (scope&, configure_post_hook*);

      static bool
      disfigure_pre (scope&, disfigure_pre_hook*);

      small_vector<configure_post_hook*, 1> configure_post_;
      small_vector<disfigure_pre_hook*,  1> disfigure_pre_;

      // Cached (during init) config.config.persist value, if defined.
      //
      const vector<pair<string, string>>* persist = nullptr;

      static const string name;
      static const uint64_t version;
    };

    // Implementation-specific utilities.
    //

    inline path
    config_file (const scope& rs)
    {
      return (rs.out_path () /
              rs.root_extra->build_dir /
              "config." + rs.root_extra->build_ext);
    }
  }
}

#endif // LIBBUILD2_CONFIG_MODULE_HXX