aboutsummaryrefslogtreecommitdiff
path: root/build
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-01-05 15:00:39 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-01-05 15:00:39 +0200
commit7e3f16c393a614e0a951abe3f7237c8169d689a9 (patch)
tree0943dbfad1e0fbf72e0ccd4f85eb2172d6fa91f6 /build
parentc0c85b67516653c181fbce7c61c2df3e31e4edd8 (diff)
Determine work, home, and {src,out}_{root,base} directories
Diffstat (limited to 'build')
-rw-r--r--build/bd.cxx62
-rw-r--r--build/buildfile5
-rw-r--r--build/context22
-rw-r--r--build/context.cxx19
-rw-r--r--build/path16
-rw-r--r--build/path.txx40
6 files changed, 160 insertions, 4 deletions
diff --git a/build/bd.cxx b/build/bd.cxx
index 66130b2..394665a 100644
--- a/build/bd.cxx
+++ b/build/bd.cxx
@@ -2,7 +2,13 @@
// copyright : Copyright (c) 2014-2015 Code Synthesis Tools CC
// license : MIT; see accompanying LICENSE file
-#include <time.h> // tzset()
+#include <time.h> // tzset()
+#include <string.h> // strerror()
+
+#include <stdlib.h> // getenv()
+#include <unistd.h> // getuid()
+#include <sys/types.h> // uid_t
+#include <pwd.h> // struct passwd, getpwuid()
#include <vector>
#include <cassert>
@@ -18,6 +24,7 @@
#include <build/algorithm>
#include <build/process>
#include <build/diagnostics>
+#include <build/context>
#include <build/lexer>
#include <build/parser>
@@ -147,6 +154,59 @@ main (int argc, char* argv[])
target_types.insert (cxx::ixx::static_type);
target_types.insert (cxx::txx::static_type);
+ // Figure out directories: work, home, and {src,out}_{root,base}.
+ //
+ work = path::current ();
+
+ if (const char* h = getenv ("HOME"))
+ home = path (h);
+ else
+ {
+ struct passwd* pw (getpwuid (getuid ()));
+
+ if (pw == nullptr)
+ {
+ const char* msg (strerror (errno));
+ cerr << "error: unable to determine home directory: " << msg << endl;
+ return 1;
+ }
+
+ home = path (pw->pw_dir);
+ }
+
+ //@@ 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)
+ {
+ 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));
+
+ cerr << "work dir: " << work << endl;
+ cerr << "home dir: " << home << endl;
+ cerr << "out_base: " << out_base << endl;
+ cerr << "src_base: " << src_base << endl;
+ cerr << "out_root: " << out_root << endl;
+ cerr << "src_root: " << src_root << endl;
+
// Parse buildfile.
//
path bf ("buildfile");
diff --git a/build/buildfile b/build/buildfile
index 4e9aaa2..8bd80b7 100644
--- a/build/buildfile
+++ b/build/buildfile
@@ -1,5 +1,5 @@
-exe{bd}: obj{bd algorithm scope parser lexer target prerequisite rule \
- native cxx/target cxx/rule process timestamp path}
+exe{bd1}: obj{bd algorithm scope parser lexer target prerequisite rule \
+ native context cxx/target cxx/rule process timestamp path}
obj{bd}: cxx{bd}
obj{algorithm}: cxx{algorithm}
@@ -10,6 +10,7 @@ obj{target}: cxx{target}
obj{prerequisite}: cxx{prerequisite}
obj{rule}: cxx{rule}
obj{native}: cxx{native}
+obj{context}: cxx{context}
obj{cxx/target}: cxx{cxx/target}
obj{cxx/rule}: cxx{cxx/rule}
obj{process}: cxx{process}
diff --git a/build/context b/build/context
new file mode 100644
index 0000000..4c86b14
--- /dev/null
+++ b/build/context
@@ -0,0 +1,22 @@
+// file : build/context -*- C++ -*-
+// copyright : Copyright (c) 2014-2015 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef BUILD_CONTEXT
+#define BUILD_CONTEXT
+
+#include <build/path>
+
+namespace build
+{
+ extern path work;
+ extern path home;
+
+ extern path src_root;
+ extern path out_root;
+
+ extern path src_base;
+ extern path out_base;
+}
+
+#endif // BUILD_CONTEXT
diff --git a/build/context.cxx b/build/context.cxx
new file mode 100644
index 0000000..ce80324
--- /dev/null
+++ b/build/context.cxx
@@ -0,0 +1,19 @@
+// file : build/context.cxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2015 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#include <build/context>
+
+using namespace std;
+
+namespace build
+{
+ path work;
+ path home;
+
+ path src_root;
+ path out_root;
+
+ path src_base;
+ path out_base;
+}
diff --git a/build/path b/build/path
index bdb9b72..ccc1b85 100644
--- a/build/path
+++ b/build/path
@@ -224,12 +224,26 @@ namespace build
basic_path
leaf () const;
+ // Return the path without the specified directory part. Throws
+ // invalid_path if the directory is not a prefix of *this. Expects
+ // both paths to be normalized.
+ //
+ basic_path
+ leaf (basic_path const&) const;
+
// Return the directory part of the path or empty path if
// there is no directory.
//
basic_path
directory () const;
+ // Return the directory part of the path without the specified
+ // leaf part. Throws invalid_path if the leaf is not a suffix of
+ // *this. Expects both paths to be normalized.
+ //
+ basic_path
+ directory (basic_path const&) const;
+
// Return the path without the extension, if any.
//
basic_path
@@ -297,7 +311,7 @@ namespace build
}
public:
- string_type
+ const string_type&
string () const
{
return path_;
diff --git a/build/path.txx b/build/path.txx
index 1502071..6a01547 100644
--- a/build/path.txx
+++ b/build/path.txx
@@ -104,6 +104,46 @@ namespace build
}
template <typename C>
+ basic_path<C> basic_path<C>::
+ leaf (basic_path<C> const& d) const
+ {
+ size_type n (d.path_.size ());
+
+ if (n == 0)
+ return *this;
+
+ size_type m (path_.size ());
+
+ if (m < n || path_.compare (0, n, d.path_) != 0)
+ throw invalid_basic_path<C> (path_);
+
+ if (n != m)
+ n++; // Skip the directory separator.
+
+ return basic_path (path_.c_str () + n, m - n);
+ }
+
+ template <typename C>
+ basic_path<C> basic_path<C>::
+ directory (basic_path<C> const& l) const
+ {
+ size_type n (l.path_.size ());
+
+ if (n == 0)
+ return *this;
+
+ size_type m (path_.size ());
+
+ if (m < n || path_.compare (m - n, n, l.path_) != 0)
+ throw invalid_basic_path<C> (path_);
+
+ if (n != m)
+ n++; // Skip the directory separator.
+
+ return basic_path (path_.c_str (), m - n);
+ }
+
+ template <typename C>
basic_path<C>& basic_path<C>::
normalize ()
{