aboutsummaryrefslogtreecommitdiff
path: root/build2/module.cxx
blob: f1e7dd3454ac10d890911abcb87fc604c424f3ac (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
// file      : build2/module.cxx -*- C++ -*-
// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
// license   : MIT; see accompanying LICENSE file

#include <build2/module.hxx>

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

using namespace std;

namespace build2
{
  available_module_map builtin_modules;

  void
  boot_module (scope& rs, const string& name, const location& loc)
  {
    // First see if this modules has already been loaded for this project.
    //
    loaded_module_map& lm (rs.modules);
    auto i (lm.find (name));

    if (i != lm.end ())
    {
      module_state& s (i->second);

      // The only valid situation here is if the module has already been
      // bootstrapped.
      //
      assert (s.boot);
      return;
    }

    // Otherwise search for this module.
    //
    auto j (builtin_modules.find (name));

    if (j == builtin_modules.end ())
      fail (loc) << "unknown module " << name;

    const module_functions& mf (j->second);

    if (mf.boot == nullptr)
      fail (loc) << "module " << name << " shouldn't be loaded in bootstrap";

    i = lm.emplace (name, module_state {true, mf.init, nullptr, loc}).first;
    mf.boot (rs, loc, i->second.module);
  }

  bool
  load_module (scope& rs,
               scope& bs,
               const string& name,
               const location& loc,
               bool opt,
               const variable_map& hints)
  {
    // First see if this modules has already been loaded for this project.
    //
    loaded_module_map& lm (rs.modules);
    auto i (lm.find (name));
    bool f (i == lm.end ());

    if (f)
    {
      // Otherwise search for this module.
      //
      auto j (builtin_modules.find (name));

      if (j == builtin_modules.end ())
      {
        if (!opt)
          fail (loc) << "unknown module " << name;
      }
      else
      {
        const module_functions& mf (j->second);

        if (mf.boot != nullptr)
          fail (loc) << "module " << name << " should be loaded in bootstrap";

        i = lm.emplace (
          name, module_state {false, mf.init, nullptr, loc}).first;
      }
    }
    else
    {
      module_state& s (i->second);

      if (s.boot)
      {
        s.boot = false;
        f = true; // This is a first call to init.
      }
    }

    bool l (i != lm.end ());
    bool c (l &&
            i->second.init (rs, bs, loc, i->second.module, f, opt, hints));

    auto& vp (var_pool.rw (rs));

    // Note: pattern-typed in context.cxx:reset() as project-visibility
    // variables of type bool.
    //
    bs.assign (vp.insert (name + ".loaded"))     = l;
    bs.assign (vp.insert (name + ".configured")) = c;

    return l && c;
  }
}