aboutsummaryrefslogtreecommitdiff
path: root/build/rule.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-03-25 14:48:36 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-03-25 14:48:36 +0200
commitcd75e06a87aa74aa6968113107afa53d401d20bc (patch)
tree1e104829d10f375a783d6efbbf7eef3e2c6d2ef5 /build/rule.cxx
parenta94dcda7f00b10cb22b5f2138b1c29bcfbe7de37 (diff)
Configure/disfigure src_root saving/removing support; fsdir{} injection
We can now build out-of-tree.
Diffstat (limited to 'build/rule.cxx')
-rw-r--r--build/rule.cxx99
1 files changed, 32 insertions, 67 deletions
diff --git a/build/rule.cxx b/build/rule.cxx
index aa0300a..fb5af3f 100644
--- a/build/rule.cxx
+++ b/build/rule.cxx
@@ -7,6 +7,7 @@
#include <utility> // move()
#include <system_error>
+#include <build/scope>
#include <build/algorithm>
#include <build/diagnostics>
#include <build/timestamp>
@@ -78,9 +79,7 @@ namespace build
return pt.mtime () != timestamp_nonexistent ? &t : nullptr;
}
default:
- {
- return &t;
- }
+ return &t;
}
}
@@ -156,13 +155,15 @@ namespace build
apply (action a, target& t, void*) const
{
// When cleaning, ignore prerequisites that are not in the same
- // or a subdirectory of ours.
+ // or a subdirectory of ours. For default, we don't do anything
+ // other than letting our prerequisites do their thing.
//
switch (a.operation ())
{
+ case default_id:
case update_id: search_and_match (a, t); break;
- case clean_id: search_and_match (a, t, t.dir); break;
- default: assert (false);
+ case clean_id: search_and_match (a, t, t.dir); break;
+ default: assert (false);
}
return default_recipe;
@@ -181,29 +182,34 @@ namespace build
{
switch (a.operation ())
{
+ // For default, we don't do anything other than letting our
+ // prerequisites do their thing.
+ //
+ case default_id:
case update_id:
- {
- search_and_match (a, t);
- break;
- }
+ search_and_match (a, t);
+ break;
+ // For clean, ignore prerequisites that are not in the same or a
+ // subdirectory of ours (if t.dir is foo/bar/, then "we" are bar
+ // and our directory is foo/). Just meditate on it a bit and you
+ // will see the light.
+ //
case clean_id:
- {
- // Ignore prerequisites that are not in the same or a subdirectory
- // of ours (if t.dir is foo/bar/, then "we" are bar and our directory
- // is foo/). Just meditate on it a bit and you will see the light.
- //
- search_and_match (a, t, t.dir.root () ? t.dir : t.dir.directory ());
- break;
- }
+ search_and_match (a, t, t.dir.root () ? t.dir : t.dir.directory ());
+ break;
default:
assert (false);
}
+ // Inject dependency on the parent directory.
+ //
+ inject_parent_fsdir (a, t);
+
switch (a)
{
case perform_update_id: return &perform_update;
case perform_clean_id: return &perform_clean;
- default: return noop_recipe;
+ default: return default_recipe; // Forward to prerequisites.
}
}
@@ -220,6 +226,11 @@ namespace build
const path& d (t.dir); // Everything is in t.dir.
+ // Generally, it is probably correct to assume that in the majority
+ // of cases the directory will already exist. If so, then we are
+ // going to get better performance by first checking if it indeed
+ // exists. See try_mkdir() for details.
+ //
if (!dir_exists (d))
{
if (verb >= 1)
@@ -229,7 +240,7 @@ namespace build
try
{
- mkdir (d);
+ try_mkdir (d);
}
catch (const system_error& e)
{
@@ -249,53 +260,7 @@ namespace build
// The reverse order of update: first delete this directory,
// then clean prerequisites (e.g., delete parent directories).
//
- const path& d (t.dir); // Everything is in t.dir.
- bool w (d == work); // Don't try to delete working directory.
-
- rmdir_status rs;
-
- // We don't want to print the command if we couldn't delete the
- // directory because it does not exist (just like we don't print
- // mkdir if it already exists) or if it is not empty. This makes
- // the below code a bit ugly.
- //
- try
- {
- rs = !w ? try_rmdir (d) : rmdir_status::not_empty;
- }
- catch (const system_error& e)
- {
- if (verb >= 1)
- text << "rmdir " << d.string ();
- else
- text << "rmdir " << t;
-
- fail << "unable to delete directory " << d.string () << ": "
- << e.what ();
- }
-
- switch (rs)
- {
- case rmdir_status::success:
- {
- if (verb >= 1)
- text << "rmdir " << d.string ();
- else
- text << "rmdir " << t;
-
- break;
- }
- case rmdir_status::not_empty:
- {
- if (verb >= 1)
- text << "directory " << d.string () << " is "
- << (w ? "cwd" : "not empty") << ", not removing";
-
- break;
- }
- case rmdir_status::not_exist:
- break;
- }
+ rmdir_status rs (rmdir (t.dir, t));
target_state ts (target_state::unchanged);