aboutsummaryrefslogtreecommitdiff
path: root/build/rule.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-02-24 06:09:23 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-02-24 06:09:23 +0200
commit5fc53bd74c7635a292cef041180da4cd32b7fb12 (patch)
tree917de261e05b203e5b152ec4f0232eb20a14a07a /build/rule.cxx
parentdea0d0913711f23fff3b902e3aa6006c6b54905a (diff)
Add fsdir{} for creating directories
Diffstat (limited to 'build/rule.cxx')
-rw-r--r--build/rule.cxx59
1 files changed, 59 insertions, 0 deletions
diff --git a/build/rule.cxx b/build/rule.cxx
index dcb6df1..e57feca 100644
--- a/build/rule.cxx
+++ b/build/rule.cxx
@@ -4,10 +4,15 @@
#include <build/rule>
+#include <string.h> // strerror_r()
+#include <sys/stat.h> // mkdir()
+#include <sys/types.h> // mkdir()
+
#include <utility> // move()
#include <build/algorithm>
#include <build/diagnostics>
+#include <build/timestamp>
using namespace std;
@@ -121,4 +126,58 @@ namespace build
//
return update_prerequisites (t);
}
+
+ // fsdir_rule
+ //
+ void* fsdir_rule::
+ match (target& t, const string&) const
+ {
+ return &t;
+ }
+
+ recipe fsdir_rule::
+ apply (target& t, void*) const
+ {
+ // Let's not allow any prerequisites for this target since it
+ // doesn't make much sense. The sole purpose of this target type
+ // is to create a directory.
+ //
+ if (!t.prerequisites.empty ())
+ fail << "no prerequisites allowed for target " << t;
+
+ return &update;
+ }
+
+ target_state fsdir_rule::
+ update (target& t)
+ {
+ path d (t.dir / path (t.name));
+
+ // Add the extension back if it was specified.
+ //
+ if (t.ext != nullptr)
+ {
+ d += '.';
+ d += *t.ext;
+ }
+
+ if (path_mtime (d) != timestamp_nonexistent)
+ return target_state::uptodate;
+
+ if (verb >= 1)
+ text << "mkdir " << d.string ();
+ else
+ text << "mkdir " << t; //@@ Probably only show if [show]?
+
+ if (mkdir (d.string ().c_str (), 0777) != 0)
+ {
+ char b[512];
+ const char* m (strerror_r (errno, b, sizeof (b)) == 0
+ ? b
+ : "error message too long");
+ fail << "mkdir: unable to create directory " << d.string () << ": " << m;
+ }
+
+ return target_state::updated;
+ }
}