aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/b.cxx6
-rw-r--r--build/rule13
-rw-r--r--build/rule.cxx59
-rw-r--r--build/target17
-rw-r--r--build/target.cxx9
5 files changed, 103 insertions, 1 deletions
diff --git a/build/b.cxx b/build/b.cxx
index 1edce6b..05dac4c 100644
--- a/build/b.cxx
+++ b/build/b.cxx
@@ -84,6 +84,7 @@ main (int argc, char* argv[])
//
target_types.insert (file::static_type);
target_types.insert (dir::static_type);
+ target_types.insert (fsdir::static_type);
target_types.insert (exe::static_type);
target_types.insert (obj::static_type);
@@ -164,7 +165,7 @@ main (int argc, char* argv[])
try
{
- p.parse (ifs, bf, scopes[path::current ()]);
+ p.parse (ifs, bf, scopes[out_base]);
}
catch (const std::ios_base::failure&)
{
@@ -184,6 +185,9 @@ main (int argc, char* argv[])
dir_rule dir_r;
rules[typeid (dir)].emplace ("dir", dir_r);
+ fsdir_rule fsdir_r;
+ rules[typeid (fsdir)].emplace ("fsdir", fsdir_r);
+
path_rule path_r;
rules[typeid (path_target)].emplace ("path", path_r);
diff --git a/build/rule b/build/rule
index cbaac04..4336c8f 100644
--- a/build/rule
+++ b/build/rule
@@ -58,6 +58,19 @@ namespace build
static target_state
update (target&);
};
+
+ class fsdir_rule: public rule
+ {
+ public:
+ virtual void*
+ match (target&, const std::string& hint) const;
+
+ virtual recipe
+ apply (target&, void*) const;
+
+ static target_state
+ update (target&);
+ };
}
#endif // BUILD_RULE
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;
+ }
}
diff --git a/build/target b/build/target
index da5cf71..881bfb7 100644
--- a/build/target
+++ b/build/target
@@ -255,6 +255,23 @@ namespace build
virtual const target_type& type () const {return static_type;}
static const target_type static_type;
};
+
+ // While a filesystem directory is mtime-based, the semantics is
+ // not very useful in our case. In particular, if another target
+ // depends on fsdir{}, then all that's desired is the creation of
+ // the directory if it doesn't already exist. In particular, we
+ // don't want to update the target just because some unrelated
+ // entry was created in that directory.
+ //
+ class fsdir: public target
+ {
+ public:
+ using target::target;
+
+ public:
+ virtual const target_type& type () const {return static_type;}
+ static const target_type static_type;
+ };
}
#endif // BUILD_TARGET
diff --git a/build/target.cxx b/build/target.cxx
index 50a7cc6..235ceef 100644
--- a/build/target.cxx
+++ b/build/target.cxx
@@ -212,4 +212,13 @@ namespace build
&target_factory<dir>,
&search_alias
};
+
+ const target_type fsdir::static_type
+ {
+ typeid (fsdir),
+ "fsdir",
+ &target::static_type,
+ &target_factory<fsdir>,
+ target::static_type.search
+ };
}