aboutsummaryrefslogtreecommitdiff
path: root/build/b.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'build/b.cxx')
-rw-r--r--build/b.cxx244
1 files changed, 113 insertions, 131 deletions
diff --git a/build/b.cxx b/build/b.cxx
index 14b23fc..3d19131 100644
--- a/build/b.cxx
+++ b/build/b.cxx
@@ -13,7 +13,7 @@
#include <vector>
#include <cassert>
#include <fstream>
-#include <iostream>
+#include <iostream> //@@ TMP, for dump()
#include <typeinfo>
#include <system_error>
@@ -25,6 +25,7 @@
#include <build/process>
#include <build/diagnostics>
#include <build/context>
+#include <build/utility>
#include <build/lexer>
#include <build/parser>
@@ -44,7 +45,7 @@ namespace build
{
if (!match (t))
{
- cerr << "error: no rule to update target " << t << endl;
+ error << "no rule to update target " << t;
return false;
}
}
@@ -60,7 +61,7 @@ namespace build
if (!match_recursive (*p.target))
{
- cerr << "info: required by " << t << endl;
+ info << "required by " << t;
return false;
}
}
@@ -73,7 +74,10 @@ namespace build
{
assert (t.state () == target_state::unknown);
- target_state ts;
+ auto g (
+ make_exception_guard (
+ [](target& t){info << "while building target " << t;},
+ t));
for (prerequisite& p: t.prerequisites)
{
@@ -81,26 +85,19 @@ namespace build
if (pt.state () == target_state::unknown)
{
- pt.state ((ts = update (pt)));
+ target_state ts (update (pt));
if (ts == target_state::failed)
return ts;
}
}
+ // @@ Why do we indicate failure via code rather than throw? Now
+ // there is no diagnostics via exception_guard above.
+
const recipe& r (t.recipe ());
- {
- auto g (
- make_exception_guard (
- [] (target& t)
- {
- cerr << "info: while building target " << t << endl;
- },
- t));
-
- ts = r (t);
- }
+ target_state ts (r (t));
assert (ts != target_state::unknown);
t.state (ts);
@@ -142,142 +139,128 @@ using namespace build;
int
main (int argc, char* argv[])
{
- tracer tr ("main");
-
- // Initialize time conversion data that is used by localtime_r().
- //
- tzset ();
+ try
+ {
+ tracer trace ("main");
- // Trace verbosity.
- //
- verb = 5;
+ // Initialize time conversion data that is used by localtime_r().
+ //
+ tzset ();
- // Register target types.
- //
- target_types.insert (file::static_type);
+ // Trace verbosity.
+ //
+ verb = 5;
- target_types.insert (exe::static_type);
- target_types.insert (obj::static_type);
+ // Register target types.
+ //
+ target_types.insert (file::static_type);
- target_types.insert (cxx::h::static_type);
- target_types.insert (cxx::c::static_type);
+ target_types.insert (exe::static_type);
+ target_types.insert (obj::static_type);
- target_types.insert (cxx::cxx::static_type);
- target_types.insert (cxx::hxx::static_type);
- target_types.insert (cxx::ixx::static_type);
- target_types.insert (cxx::txx::static_type);
+ target_types.insert (cxx::h::static_type);
+ target_types.insert (cxx::c::static_type);
- // Figure out directories: work, home, and {src,out}_{root,base}.
- //
- work = path::current ();
+ target_types.insert (cxx::cxx::static_type);
+ target_types.insert (cxx::hxx::static_type);
+ target_types.insert (cxx::ixx::static_type);
+ target_types.insert (cxx::txx::static_type);
- if (const char* h = getenv ("HOME"))
- home = path (h);
- else
- {
- struct passwd* pw (getpwuid (getuid ()));
+ // Figure out directories: work, home, and {src,out}_{root,base}.
+ //
+ work = path::current ();
- if (pw == nullptr)
+ if (const char* h = getenv ("HOME"))
+ home = path (h);
+ else
{
- const char* msg (strerror (errno));
- cerr << "error: unable to determine home directory: " << msg << endl;
- return 1;
- }
+ struct passwd* pw (getpwuid (getuid ()));
- home = path (pw->pw_dir);
- }
+ if (pw == nullptr)
+ {
+ const char* msg (strerror (errno));
+ fail << "unable to determine home directory: " << msg;
+ }
+
+ home = path (pw->pw_dir);
+ }
- //@@ Must be normalized.
- //
- out_base = work;
- src_base = out_base;
+ //@@ Must be normalized.
+ //
+ out_base = work;
+ src_base = out_base;
- // The project's root directory is the one that contains the build/
- // sub-directory which contains the pre.build file.
- //
- for (path d (src_base); !d.root () && d != home; d = d.directory ())
- {
- path f (d / path ("build/pre.build"));
- if (path_mtime (f) != timestamp_nonexistent)
+ // The project's root directory is the one that contains the build/
+ // sub-directory which contains the pre.build file.
+ //
+ for (path d (src_base); !d.root () && d != home; d = d.directory ())
{
- src_root = d;
- break;
+ path f (d / path ("build/pre.build"));
+ if (path_mtime (f) != timestamp_nonexistent)
+ {
+ src_root = d;
+ break;
+ }
}
- }
- if (src_root.empty ())
- {
- src_root = src_base;
- out_root = out_base;
- }
- else
- out_root = out_base.directory (src_base.leaf (src_root));
+ if (src_root.empty ())
+ {
+ src_root = src_base;
+ out_root = out_base;
+ }
+ else
+ out_root = out_base.directory (src_base.leaf (src_root));
- if (verb >= 4)
- {
- tr << "work dir: " << work.string ();
- tr << "home dir: " << home.string ();
- tr << "out_base: " << out_base.string ();
- tr << "src_base: " << src_base.string ();
- tr << "out_root: " << out_root.string ();
- tr << "src_root: " << src_root.string ();
- }
+ if (verb >= 4)
+ {
+ trace << "work dir: " << work.string ();
+ trace << "home dir: " << home.string ();
+ trace << "out_base: " << out_base.string ();
+ trace << "src_base: " << src_base.string ();
+ trace << "out_root: " << out_root.string ();
+ trace << "src_root: " << src_root.string ();
+ }
- // Parse buildfile.
- //
- path bf ("buildfile");
+ // Parse buildfile.
+ //
+ path bf ("buildfile");
- ifstream ifs (bf.string ().c_str ());
- if (!ifs.is_open ())
- {
- cerr << "error: unable to open " << bf << " in read mode" << endl;
- return 1;
- }
+ ifstream ifs (bf.string ().c_str ());
+ if (!ifs.is_open ())
+ fail << "unable to open " << bf;
- ifs.exceptions (ifstream::failbit | ifstream::badbit);
- parser p (cerr);
+ ifs.exceptions (ifstream::failbit | ifstream::badbit);
+ parser p;
- try
- {
- p.parse (ifs, bf, scopes[path::current ()]);
- }
- catch (const lexer_error&)
- {
- return 1; // Diagnostics has already been issued.
- }
- catch (const parser_error&)
- {
- return 1; // Diagnostics has already been issued.
- }
- catch (const std::ios_base::failure&)
- {
- cerr << "error: failed to read from " << bf << endl;
- return 1;
- }
+ try
+ {
+ p.parse (ifs, bf, scopes[path::current ()]);
+ }
+ catch (const std::ios_base::failure&)
+ {
+ fail << "failed to read from " << bf;
+ }
- dump ();
+ dump ();
- // Register rules.
- //
- cxx::link cxx_link;
- rules[typeid (exe)].emplace ("cxx.gnu.link", cxx_link);
+ // Register rules.
+ //
+ cxx::link cxx_link;
+ rules[typeid (exe)].emplace ("cxx.gnu.link", cxx_link);
- cxx::compile cxx_compile;
- rules[typeid (obj)].emplace ("cxx.gnu.compile", cxx_compile);
+ cxx::compile cxx_compile;
+ rules[typeid (obj)].emplace ("cxx.gnu.compile", cxx_compile);
- default_path_rule path_exists;
- rules[typeid (path_target)].emplace ("", path_exists);
+ default_path_rule path_exists;
+ rules[typeid (path_target)].emplace ("", path_exists);
- // Build.
- //
- if (default_target == nullptr)
- {
- cerr << "error: no default target" << endl;
- return 1;
- }
+ // Build.
+ //
+ if (default_target == nullptr)
+ {
+ fail << "no default target";
+ }
- try
- {
target& d (*default_target);
if (!match_recursive (d))
@@ -289,27 +272,26 @@ main (int argc, char* argv[])
{
case target_state::uptodate:
{
- cerr << "info: target " << d << " is up to date" << endl;
+ info << "target " << d << " is up to date";
break;
}
case target_state::updated:
break;
case target_state::failed:
{
- cerr << "error: failed to update target " << d << endl;
- return 1;
+ fail << "failed to update target " << d;
}
case target_state::unknown:
assert (false);
}
}
- catch (const error&)
+ catch (const failed&)
{
return 1; // Diagnostics has already been issued.
}
catch (const std::exception& e)
{
- cerr << "error: " << e.what () << endl;
+ error << e.what ();
return 1;
}
}