aboutsummaryrefslogtreecommitdiff
path: root/bdep/build.txx
blob: b83aa9c3f59f71b8cae1efb33d07d339e7106985 (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
// file      : bdep/build.txx -*- C++ -*-
// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
// license   : MIT; see accompanying LICENSE file

#include <cstring> // strchr()

#include <bdep/project.hxx>
#include <bdep/database.hxx>
#include <bdep/diagnostics.hxx>

#include <bdep/sync.hxx>

namespace bdep
{
  template <typename O>
  int
  cmd_build (const O& o,
             void (*build) (const O&,
                            const shared_ptr<configuration>&,
                            const cstrings&,
                            const strings&),
             cli::scanner& args)
  {
    tracer trace ("build");

    // Save cfg-vars with some sanity checking.
    //
    strings cfg_vars;
    while (args.more ())
    {
      const char* a (args.next ());

      if (strchr (a , '=') == nullptr)
        fail << "'" << a << "' does not look like a variable assignment";

      cfg_vars.push_back (a);
    }

    // The same ignore/load story as in sync.
    //
    project_packages pp (
      find_project_packages (o,
                             false /* ignore_packages */,
                             false /* load_packages   */));

    const dir_path& prj (pp.project);

    // Load the configurations without keeping the database open longer
    // than necessary.
    //
    configurations cfgs;
    {
      database db (open (prj, trace));

      transaction t (db.begin ());
      cfgs = find_configurations (o, prj, t);
      t.commit ();
    }

    // If specified, verify packages are present in each configuration.
    //
    if (!pp.packages.empty ())
      verify_project_packages (pp, cfgs);

    // If no packages were explicitly specified, then we build all that have
    // been initialized in each configuration.
    //
    cstrings pkgs;

    bool all (pp.packages.empty ());
    if (!all)
    {
      for (const package_location& p: pp.packages)
        pkgs.push_back (p.name.string ().c_str ());
    }

    // Build in each configuration skipping empty ones.
    //
    bool first (true);
    for (const shared_ptr<configuration>& c: cfgs)
    {
      if (c->packages.empty ())
      {
        if (verb)
          info << "skipping empty configuration " << *c;

        continue;
      }

      // Collect packages.
      //
      if (all)
      {
        pkgs.clear ();

        for (const package_state& p: c->packages)
          pkgs.push_back (p.name.string ().c_str ());
      }

      // If we are printing multiple configurations, separate them with a
      // blank line and print the configuration name/directory.
      //
      if (verb && cfgs.size () > 1)
      {
        text << (first ? "" : "\n")
             << "in configuration " << *c << ':';

        first = false;
      }

      // Pre-sync the configuration to avoid triggering the build system
      // hook (see sync for details).
      //
      cmd_sync (o, prj, c, strings () /* pkg_args */, true /* implicit */);

      build (o, c, pkgs, cfg_vars);
    }

    return 0;
  }
}