aboutsummaryrefslogtreecommitdiff
path: root/bpkg/package-skeleton.hxx
blob: 00be6a3539e2621bfa25cea67d8b7ae14b6ccf1c (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
// file      : bpkg/package-skeleton.hxx -*- C++ -*-
// license   : MIT; see accompanying LICENSE file

#ifndef BPKG_PACKAGE_SKELETON_HXX
#define BPKG_PACKAGE_SKELETON_HXX

#include <libbuild2/forward.hxx> // build2::context

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

#include <bpkg/package.hxx>

namespace bpkg
{
  // A build system skeleton of a package used to evaluate buildfile clauses
  // during dependency resolution (enable, reflect, require or prefer/accept).
  //
  class package_skeleton
  {
  public:
    // If the package is external and will not be disfigured, then the
    // existing package source root directory needs to be specified. In this
    // case this source directory and the automatically deduced potentially
    // non-existing out root directory will be used for build2 state loading
    // instead of the newly created skeleton directory. This, in particular,
    // allows to consider existing configuration variables while evaluating
    // the dependency clauses.
    //
    // Note that the database and available_package are expected to outlive
    // this object.
    //
    // Note also that this creates an "unloaded" skeleton and is therefore
    // cheap.
    //
    // @@ Note that storing the list of configuration variables by reference
    //    complicates its use in pkg-build, where both the configuration and
    //    the optional skeleton are parts of the same copyable/moveable
    //    build_package object. We could probably move the configuration into
    //    the skeleton if create it, complicating an access to the
    //    configuration for the users (if the skeleton is present then get
    //    configuration from it, etc). Let's however keep it simple for now
    //    and just copy the configuration.
    //
    package_skeleton (database&,
                      const available_package&,
                      const strings& cvs,
                      optional<dir_path> src_root);

    // Evaluate the enable clause.
    //
    // @@ What can we pass as location? Maybe somehow point to manifest in the
    //    skeleton (will need to re-acquire the position somehow)?
    //
    bool
    evaluate_enable (const string&)
    {
      // @@ TMP
      //
      fail << "conditional dependency for package " << name () <<
        info << "conditional dependencies are not yet supported";

      load ();

      // TODO

      return true; // @@ TMP
    }

    // Evaluate the reflect clause.
    //
    void
    evaluate_reflect (const string& r)
    {
      load ();

      // TODO

      // @@ DEP For now we assume that the reflection, if present, contains
      //    a single configuration variable that assigns a literal value.
      //
      reflect_.push_back (r);

      // Mark the build system state as needing reloading since some computed
      // values in root.build may depend on the new configuration values.
      //
      dirty_ = true;
    }

    // Return the accumulated reflect values.
    //
    strings
    collect_reflect ()
    {
      return reflect_;
    }

    const package_name&
    name () const {return available_.get ().id.name;}

    // Implementation details.
    //
    // We have to define these because context is forward-declared. Also, copy
    // constructor has some special logic.
    //
    ~package_skeleton ();
    package_skeleton (package_skeleton&&);
    package_skeleton& operator= (package_skeleton&&);

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

  private:
    // Create the skeleton if necessary and (re)load the build system state.
    //
    // Call this function before evaluating every clause.
    //
    void
    load ();

  private:
    // NOTE: remember to update move/copy constructors!
    //
    reference_wrapper<database> db_;
    reference_wrapper<const available_package> available_;
    strings config_vars_;

    optional<dir_path> src_root_;
    optional<dir_path> out_root_;

    unique_ptr<build2::context> ctx_;
    bool created_ = false;
    bool dirty_ = false;

    strings reflect_;
  };
}

#endif // BPKG_PACKAGE_SKELETON_HXX