aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/file.hxx
blob: ce57933a65391ed23106585c794e7ca4ad0a7048 (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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
// file      : libbuild2/file.hxx -*- C++ -*-
// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
// license   : MIT; see accompanying LICENSE file

#ifndef LIBBUILD2_FILE_HXX
#define LIBBUILD2_FILE_HXX

#include <map>

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

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

#include <libbuild2/export.hxx>

namespace build2
{
  class lexer;

  using subprojects = std::map<project_name, dir_path>;

  LIBBUILD2_SYMEXPORT ostream&
  operator<< (ostream&, const subprojects&); // Print as name@dir sequence.

  LIBBUILD2_SYMEXPORT extern const dir_path std_build_dir;  // build/

  // build/root.build
  //
  LIBBUILD2_SYMEXPORT extern const path std_root_file;

  // build/bootstrap.build
  //
  LIBBUILD2_SYMEXPORT extern const path std_bootstrap_file;

  LIBBUILD2_SYMEXPORT extern const path std_buildfile_file; // buildfile
  LIBBUILD2_SYMEXPORT extern const path alt_buildfile_file; // build2file

  // If the altn argument value is present, then it indicates whether we are
  // using the standard or the alternative build file/directory naming.
  //
  // The overall plan is to run various "file exists" tests using the standard
  // and the alternative names. The first test that succeeds determines the
  // naming scheme (by setting altn) and from then on all the remaining tests
  // only look for things in this scheme.
  //
  LIBBUILD2_SYMEXPORT bool
  is_src_root (const dir_path&, optional<bool>& altn);

  LIBBUILD2_SYMEXPORT bool
  is_out_root (const dir_path&, optional<bool>& altn);

  // Given an src_base directory, look for a project's src_root based on the
  // presence of known special files. Return empty path if not found. Note
  // that if the input is normalized/actualized, then the output will be as
  // well.
  //
  LIBBUILD2_SYMEXPORT dir_path
  find_src_root (const dir_path&, optional<bool>& altn);

  // The same as above but for project's out. Note that we also check whether
  // a directory happens to be src_root, in case this is an in-tree build with
  // the result returned as the second half of the pair. Note also that if the
  // input is normalized/actualized, then the output will be as well.
  //
  LIBBUILD2_SYMEXPORT pair<dir_path, bool>
  find_out_root (const dir_path&, optional<bool>& altn);

  // If buildfile is '-', then read from STDIN.
  //
  LIBBUILD2_SYMEXPORT void
  source (scope& root, scope& base, const path&);

  // As above, but extract from a stream. The name argument is used for
  // diagnostics.
  //
  LIBBUILD2_SYMEXPORT void
  source (scope& root, scope& base, istream&, const path_name&);

  // As above, but extract from a lexer (this could be useful for sourcing
  // stdin that requires parse_variable()).
  //
  LIBBUILD2_SYMEXPORT void
  source (scope& root, scope& base, lexer&);

  // As above but first check if this buildfile has already been sourced for
  // the base scope. Return false if the file has already been sourced.
  //
  bool
  source_once (scope& root, scope& base, const path&);

  // As above but checks against the specified scope rather than base.
  //
  LIBBUILD2_SYMEXPORT bool
  source_once (scope& root, scope& base, const path&, scope& once);

  // Create project's root scope. Only set the src_root variable if the passed
  // src_root value is not empty. The scope argument is only used for context
  // and as a proof of lock.
  //
  LIBBUILD2_SYMEXPORT scope_map::iterator
  create_root (scope&, const dir_path& out_root, const dir_path& src_root);

  // Setup root scope. Note that it assumes the src_root variable has already
  // been set.
  //
  LIBBUILD2_SYMEXPORT void
  setup_root (scope&, bool forwarded);

  // Setup the base scope (set *_base variables, etc).
  //
  LIBBUILD2_SYMEXPORT scope&
  setup_base (scope_map::iterator,
              const dir_path& out_base,
              const dir_path& src_base);

  // Return a scope for the specified directory (first). Note that switching
  // to this scope might also involve switch to a new root scope (second) if
  // the new scope is in another project. If the new scope is not in any
  // project, then NULL is returned in second.
  //
  LIBBUILD2_SYMEXPORT pair<scope&, scope*>
  switch_scope (scope& root, const dir_path&);

  // Bootstrap and optionally load an ad hoc (sub)project (i.e., the kind that
  // is not discovered and loaded automatically by bootstrap/load functions
  // above).
  //
  // Note that we expect the outer project (if any) to be bootstrapped and
  // loaded and currently we do not add the newly loaded subproject to the
  // outer project's subprojects map.
  //
  // The scope argument is only used as proof of lock.
  //
  LIBBUILD2_SYMEXPORT scope&
  load_project (scope&,
                const dir_path& out_root,
                const dir_path& src_root,
                bool forwarded,
                bool load = true);

  // Bootstrap the project's forward. Return the forwarded-to out_root or
  // src_root if there is no forward. See is_{src,out}_root() for the altn
  // argument semantics.
  //
  LIBBUILD2_SYMEXPORT dir_path
  bootstrap_fwd (context&, const dir_path& src_root, optional<bool>& altn);

  // Bootstrap the project's root scope, the out part.
  //
  LIBBUILD2_SYMEXPORT void
  bootstrap_out (scope& root, optional<bool>& altn);

  // Bootstrap the project's root scope, the src part. Return true if we
  // loaded anything (which confirms the src_root is not bogus).
  //
  LIBBUILD2_SYMEXPORT bool
  bootstrap_src (scope& root, optional<bool>& altn);

  // Return true if this scope has already been bootstrapped, that is, the
  // following calls have already been made:
  //
  //   bootstrap_out()
  //   setup_root()
  //   bootstrap_src()
  //
  LIBBUILD2_SYMEXPORT bool
  bootstrapped (scope& root);

  // Execute pre/post-bootstrap hooks. Similar to bootstrap_out/src(), should
  // only be called once per project bootstrap.
  //
  LIBBUILD2_SYMEXPORT void
  bootstrap_pre (scope& root, optional<bool>& altn);

  LIBBUILD2_SYMEXPORT void
  bootstrap_post (scope& root);

  // Create and bootstrap outer root scopes, if any. Loading is done by
  // load_root().
  //
  LIBBUILD2_SYMEXPORT void
  create_bootstrap_outer (scope& root);

  // Create and bootstrap inner root scopes, if any, recursively.
  //
  // If out_base is not empty, then only bootstrap scope between root and base
  // returning the innermost created root scope or root if none were created.
  //
  // Note that loading is done by load_root().
  //
  LIBBUILD2_SYMEXPORT scope&
  create_bootstrap_inner (scope& root, const dir_path& out_base = dir_path ());

  // Load project's root.build (and root pre/post hooks) unless already
  // loaded. Also make sure all outer root scopes are loaded prior to loading
  // this root scope.
  //
  LIBBUILD2_SYMEXPORT void
  load_root (scope& root);

  // Extract the specified variable value from a buildfile. It is expected to
  // be the first non-comment line and not to rely on any variable expansion
  // other than those from the global scope or any variable overrides. Return
  // an indication of whether the variable was found.
  //
  LIBBUILD2_SYMEXPORT pair<value, bool>
  extract_variable (context&, const path&, const variable&);

  // As above, but extract from a stream. The name argument is used for
  // diagnostics.
  //
  LIBBUILD2_SYMEXPORT pair<value, bool>
  extract_variable (context&, istream&, const path& name, const variable&);

  // As above, but extract from a lexer (this could be useful for extracting
  // from stdin).
  //
  LIBBUILD2_SYMEXPORT pair<value, bool>
  extract_variable (context&, lexer&, const variable&);

  // Import has two phases: the first is triggered by the import directive in
  // the buildfile. It will try to find and load the project. Failed that, it
  // will return the project-qualified name of the target which will be used
  // to create a project-qualified prerequisite. This gives the rule that will
  // be searching this prerequisite a chance to do some target-type specific
  // search. For example, a C++ link rule can search for lib{} prerequisites
  // in the C++ compiler default library search paths (so that we end up with
  // functionality identical to -lfoo). If, however, the rule didn't do any of
  // that (or failed to find anything usable), it calls the standard
  // prerequisite search() function which sees this is a project-qualified
  // prerequisite and goes straight to the second phase of import. Here,
  // currently, we simply fail but in the future this will be the place where
  // we can call custom "last resort" import hooks. For example, we can hook a
  // package manager that will say, "Hey, dude, I see you are trying to import
  // foo and I see there is a package foo available in repository bar. Wanna,
  // like, download and use it or something?"
  //
  // Note also that we return names rather than a single name: while normally
  // it will be a single target name, it can be an out-qualified pair (if
  // someone wants to return a source target) but it can also be a non-target
  // since we don't restrict what users can import/export.
  //
  LIBBUILD2_SYMEXPORT names
  import (scope& base, name, const location&);

  LIBBUILD2_SYMEXPORT pair<name, dir_path>
  import_search (scope& base, name, const location&, bool subproj = true);

  LIBBUILD2_SYMEXPORT pair<names, const scope&>
  import_load (context&, pair<name, dir_path>, const location&);

  const target&
  import (context&, const prerequisite_key&);

  // As above but only imports as an already existing target. Unlike the above
  // version, this one can be called during the execute phase.
  //
  // Note: similar to search_existing().
  //
  const target*
  import_existing (context&, const prerequisite_key&);
}

#include <libbuild2/file.ixx>

#endif // LIBBUILD2_FILE_HXX