From 7e3f16c393a614e0a951abe3f7237c8169d689a9 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 5 Jan 2015 15:00:39 +0200 Subject: Determine work, home, and {src,out}_{root,base} directories --- build/bd.cxx | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- build/buildfile | 5 +++-- build/context | 22 ++++++++++++++++++++ build/context.cxx | 19 +++++++++++++++++ build/path | 16 +++++++++++++- build/path.txx | 40 +++++++++++++++++++++++++++++++++++ 6 files changed, 160 insertions(+), 4 deletions(-) create mode 100644 build/context create mode 100644 build/context.cxx (limited to 'build') 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 // tzset() +#include // tzset() +#include // strerror() + +#include // getenv() +#include // getuid() +#include // uid_t +#include // struct passwd, getpwuid() #include #include @@ -18,6 +24,7 @@ #include #include #include +#include #include #include @@ -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 + +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 + +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 + basic_path basic_path:: + leaf (basic_path 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 (path_); + + if (n != m) + n++; // Skip the directory separator. + + return basic_path (path_.c_str () + n, m - n); + } + + template + basic_path basic_path:: + directory (basic_path 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 (path_); + + if (n != m) + n++; // Skip the directory separator. + + return basic_path (path_.c_str (), m - n); + } + + template basic_path& basic_path:: normalize () { -- cgit v1.1