aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-06-18 14:41:45 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-06-18 14:41:45 +0200
commit63e7a4a77cb8ceed7b42561fe3202b0b48d86db6 (patch)
treebde5a79522225f32ec188ba46d0834486c30f00f
parent28c82c861e38fe05a25e916563e0551ed8fce91e (diff)
Move path and filesystem from build2 to libbutl
-rw-r--r--build/algorithm2
-rw-r--r--build/algorithm.cxx1
-rw-r--r--build/b.cxx6
-rw-r--r--build/bin/module2
-rw-r--r--build/buildfile5
-rw-r--r--build/config/module1
-rw-r--r--build/config/module.cxx5
-rw-r--r--build/config/operation.cxx4
-rw-r--r--build/context17
-rw-r--r--build/context.cxx1
-rw-r--r--build/context.txx8
-rw-r--r--build/cxx/module1
-rw-r--r--build/cxx/module.cxx1
-rw-r--r--build/cxx/rule1
-rw-r--r--build/cxx/rule.cxx1
-rw-r--r--build/diagnostics6
-rw-r--r--build/file3
-rw-r--r--build/file.cxx4
-rw-r--r--build/filesystem61
-rw-r--r--build/filesystem.cxx101
-rw-r--r--build/name6
-rw-r--r--build/operation2
-rw-r--r--build/parser3
-rw-r--r--build/path553
-rw-r--r--build/path-io7
-rw-r--r--build/path-map88
-rw-r--r--build/path.cxx109
-rw-r--r--build/path.ixx171
-rw-r--r--build/path.txx256
-rw-r--r--build/prerequisite2
-rw-r--r--build/rule1
-rw-r--r--build/rule.cxx5
-rw-r--r--build/scope11
-rw-r--r--build/scope.cxx4
-rw-r--r--build/search.cxx5
-rw-r--r--build/spec3
-rw-r--r--build/target4
-rw-r--r--build/target-key2
-rw-r--r--build/timestamp54
-rw-r--r--build/timestamp.cxx177
-rw-r--r--build/types21
-rw-r--r--build/utility2
-rw-r--r--build/variable3
-rw-r--r--tests/build/buildfile3
-rw-r--r--tests/build/parser/driver.cxx2
-rw-r--r--tests/build/path/buildfile1
-rw-r--r--tests/build/path/driver.cxx227
47 files changed, 95 insertions, 1858 deletions
diff --git a/build/algorithm b/build/algorithm
index c21457e..5138dfa 100644
--- a/build/algorithm
+++ b/build/algorithm
@@ -5,9 +5,9 @@
#ifndef BUILD_ALGORITHM
#define BUILD_ALGORITHM
+#include <build/types>
#include <build/target>
#include <build/operation>
-#include <build/timestamp>
namespace build
{
diff --git a/build/algorithm.cxx b/build/algorithm.cxx
index fe85c4e..2529e13 100644
--- a/build/algorithm.cxx
+++ b/build/algorithm.cxx
@@ -11,7 +11,6 @@
#include <butl/utility> // reverse_iterate
-#include <build/path>
#include <build/scope>
#include <build/target>
#include <build/prerequisite>
diff --git a/build/b.cxx b/build/b.cxx
index 24f4266..8e75c14 100644
--- a/build/b.cxx
+++ b/build/b.cxx
@@ -16,8 +16,9 @@
#include <iostream>
#include <system_error>
-#include <build/path>
-#include <build/name>
+#include <butl/filesystem>
+
+#include <build/types>
#include <build/spec>
#include <build/operation>
#include <build/scope>
@@ -30,7 +31,6 @@
#include <build/diagnostics>
#include <build/context>
#include <build/utility>
-#include <build/filesystem>
#include <build/token>
#include <build/lexer>
diff --git a/build/bin/module b/build/bin/module
index 749ce3f..e09e742 100644
--- a/build/bin/module
+++ b/build/bin/module
@@ -5,7 +5,7 @@
#ifndef BUILD_BIN_MODULE
#define BUILD_BIN_MODULE
-#include <build/path>
+#include <build/types>
#include <build/module>
namespace build
diff --git a/build/buildfile b/build/buildfile
index 8b4cb84..4cb9c59 100644
--- a/build/buildfile
+++ b/build/buildfile
@@ -5,9 +5,8 @@ bin = bin/{target rule module}
cxx = cxx/{target rule module}
exe{b}: cxx{b algorithm name operation spec scope variable target \
- prerequisite rule file module context search diagnostics token \
- lexer parser timestamp path path-io utility filesystem dump options \
- $config $bin $cxx} $libs
+ prerequisite rule file module context search diagnostics token \
+ lexer parser path-io utility dump options $config $bin $cxx} $libs
#@@ TODO
#
diff --git a/build/config/module b/build/config/module
index 317b25a..4ab3e7e 100644
--- a/build/config/module
+++ b/build/config/module
@@ -5,6 +5,7 @@
#ifndef BUILD_CONFIG_MODULE
#define BUILD_CONFIG_MODULE
+#include <build/types>
#include <build/module>
namespace build
diff --git a/build/config/module.cxx b/build/config/module.cxx
index ab7ed4e..7ac9071 100644
--- a/build/config/module.cxx
+++ b/build/config/module.cxx
@@ -4,15 +4,16 @@
#include <build/config/module>
-#include <build/path>
+#include <butl/filesystem>
+
#include <build/scope>
#include <build/file>
-#include <build/filesystem>
#include <build/diagnostics>
#include <build/config/operation>
using namespace std;
+using namespace butl;
namespace build
{
diff --git a/build/config/operation.cxx b/build/config/operation.cxx
index 567e636..89bef61 100644
--- a/build/config/operation.cxx
+++ b/build/config/operation.cxx
@@ -6,13 +6,15 @@
#include <fstream>
+#include <butl/filesystem>
+
#include <build/scope>
#include <build/file>
#include <build/context>
-#include <build/filesystem>
#include <build/diagnostics>
using namespace std;
+using namespace butl;
namespace build
{
diff --git a/build/context b/build/context
index 3a99014..dc865d2 100644
--- a/build/context
+++ b/build/context
@@ -8,10 +8,11 @@
#include <string>
#include <ostream>
-#include <build/path>
+#include <butl/filesystem>
+
+#include <build/types>
#include <build/rule>
#include <build/operation>
-#include <build/filesystem>
namespace build
{
@@ -37,7 +38,7 @@ namespace build
// The dual interface wrapper for the {mk,rm}{file,dir}() functions
// below that allows you to use it as a true/false return or a more
- // detailed enum from <filesystem>
+ // detailed enum from <butl/filesystem>
//
template <typename T>
struct fs_status
@@ -53,7 +54,7 @@ namespace build
// directory will exist in the majority of case and performance is
// important. See the fsdir{} rule for details.
//
- fs_status<mkdir_status>
+ fs_status<butl::mkdir_status>
mkdir (const dir_path&);
// Remove the file and print the standard diagnostics. The second
@@ -62,19 +63,19 @@ namespace build
// being printed.
//
template <typename T>
- fs_status<rmfile_status>
+ fs_status<butl::rmfile_status>
rmfile (const path&, const T& target);
- inline fs_status<rmfile_status>
+ inline fs_status<butl::rmfile_status>
rmfile (const path& f) {return rmfile (f, f);}
// Similar to rmfile() but for directories.
//
template <typename T>
- fs_status<rmdir_status>
+ fs_status<butl::rmdir_status>
rmdir (const dir_path&, const T& target);
- inline fs_status<rmdir_status>
+ inline fs_status<butl::rmdir_status>
rmdir (const dir_path& d) {return rmdir (d, d);}
// Return the src/out directory corresponding to the given out/src. The
diff --git a/build/context.cxx b/build/context.cxx
index 7769c94..22b6f53 100644
--- a/build/context.cxx
+++ b/build/context.cxx
@@ -12,6 +12,7 @@
#include <build/diagnostics>
using namespace std;
+using namespace butl;
namespace build
{
diff --git a/build/context.txx b/build/context.txx
index 286d460..b9004e0 100644
--- a/build/context.txx
+++ b/build/context.txx
@@ -9,9 +9,11 @@
namespace build
{
template <typename T>
- fs_status<rmfile_status>
+ fs_status<butl::rmfile_status>
rmfile (const path& f, const T& t)
{
+ using namespace butl;
+
// We don't want to print the command if we couldn't remove the
// file because it does not exist (just like we don't print the
// update command if the file is up to date). This makes the
@@ -45,9 +47,11 @@ namespace build
}
template <typename T>
- fs_status<rmdir_status>
+ fs_status<butl::rmdir_status>
rmdir (const dir_path& d, const T& t)
{
+ using namespace butl;
+
bool w (d == work); // Don't try to remove working directory.
rmdir_status rs;
diff --git a/build/cxx/module b/build/cxx/module
index 11cd7bc..2d50f59 100644
--- a/build/cxx/module
+++ b/build/cxx/module
@@ -5,6 +5,7 @@
#ifndef BUILD_CXX_MODULE
#define BUILD_CXX_MODULE
+#include <build/types>
#include <build/module>
namespace build
diff --git a/build/cxx/module.cxx b/build/cxx/module.cxx
index 4193104..21f1b85 100644
--- a/build/cxx/module.cxx
+++ b/build/cxx/module.cxx
@@ -7,7 +7,6 @@
#include <butl/process>
#include <butl/fdstream>
-#include <build/path>
#include <build/scope>
#include <build/diagnostics>
diff --git a/build/cxx/rule b/build/cxx/rule
index 686d5ae..8c575fe 100644
--- a/build/cxx/rule
+++ b/build/cxx/rule
@@ -5,6 +5,7 @@
#ifndef BUILD_CXX_RULE
#define BUILD_CXX_RULE
+#include <build/types>
#include <build/rule>
namespace build
diff --git a/build/cxx/rule.cxx b/build/cxx/rule.cxx
index c0e6550..58d8e88 100644
--- a/build/cxx/rule.cxx
+++ b/build/cxx/rule.cxx
@@ -18,7 +18,6 @@
#include <build/scope>
#include <build/variable>
#include <build/algorithm>
-#include <build/timestamp>
#include <build/diagnostics>
#include <build/context>
diff --git a/build/diagnostics b/build/diagnostics
index 05401b9..6c528f2 100644
--- a/build/diagnostics
+++ b/build/diagnostics
@@ -14,11 +14,15 @@
#include <exception>
#include <type_traits>
-#include <build/path>
+#include <butl/path>
+
#include <build/path-io>
namespace build
{
+ using butl::path;
+ using butl::dir_path;
+
// Throw this exception to terminate the build. The handler should
// assume that the diagnostics has already been issued.
//
diff --git a/build/file b/build/file
index 7f72282..7ac4d4d 100644
--- a/build/file
+++ b/build/file
@@ -5,8 +5,7 @@
#ifndef BUILD_FILE
#define BUILD_FILE
-#include <build/path>
-#include <build/name>
+#include <build/types>
#include <build/variable> // list_value
namespace build
diff --git a/build/file.cxx b/build/file.cxx
index 6f10391..5f899de 100644
--- a/build/file.cxx
+++ b/build/file.cxx
@@ -6,13 +6,15 @@
#include <fstream>
+#include <butl/filesystem>
+
#include <build/scope>
#include <build/context>
#include <build/parser>
-#include <build/filesystem>
#include <build/diagnostics>
using namespace std;
+using namespace butl;
namespace build
{
diff --git a/build/filesystem b/build/filesystem
deleted file mode 100644
index fbade4f..0000000
--- a/build/filesystem
+++ /dev/null
@@ -1,61 +0,0 @@
-// file : build/filesystem -*- C++ -*-
-// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#ifndef BUILD_FILESYSTEM
-#define BUILD_FILESYSTEM
-
-#include <sys/types.h> // mode_t
-
-#include <build/path>
-
-namespace build
-{
- // Return true if the path is to an existing directory. Note that
- // this function resolves symlinks.
- //
- bool
- dir_exists (const path&);
-
- // Return true if the path is to an existing regular file. Note that
- // this function resolves symlinks.
- //
- bool
- file_exists (const path&);
-
- // Try to create a directory unless it already exists. If you expect
- // the directory to exist and performance is important, then you
- // should first call dir_exists() above since that's what this
- // implementation will do to make sure the path is actually a
- // directory.
- //
- // You should also probably use the default mode 0777 and let the
- // umask mechanism adjust it to the user's preferences.
- //
- // Errors are reported by throwing std::system_error.
- //
- enum class mkdir_status {success, already_exists};
-
- mkdir_status
- try_mkdir (const path&, mode_t = 0777);
-
- // Try to remove the directory returning not_exist if it does not
- // exist and not_empty if it is not empty. All other errors are
- // reported by throwing std::system_error.
- //
- enum class rmdir_status {success, not_exist, not_empty};
-
- rmdir_status
- try_rmdir (const path&);
-
- // Try to remove the file (or symbolic link) returning not_exist if
- // it does not exist. All other errors are reported by throwing
- // std::system_error.
- //
- enum class rmfile_status {success, not_exist};
-
- rmfile_status
- try_rmfile (const path&);
-}
-
-#endif // BUILD_FILESYSTEM
diff --git a/build/filesystem.cxx b/build/filesystem.cxx
deleted file mode 100644
index 6485f34..0000000
--- a/build/filesystem.cxx
+++ /dev/null
@@ -1,101 +0,0 @@
-// file : build/filesystem.cxx -*- C++ -*-
-// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#include <build/filesystem>
-
-#include <unistd.h> // rmdir(), unlink()
-#include <sys/types.h> // stat
-#include <sys/stat.h> // stat, lstat(), S_IS*, mkdir()
-
-#include <system_error>
-
-using namespace std;
-
-namespace build
-{
- bool
- dir_exists (const path& p)
- {
- struct stat s;
- if (::lstat (p.string ().c_str (), &s) != 0)
- {
- if (errno == ENOENT || errno == ENOTDIR)
- return false;
- else
- throw system_error (errno, system_category ());
- }
-
- return S_ISDIR (s.st_mode);
- }
-
- bool
- file_exists (const path& p)
- {
- struct stat s;
- if (::lstat (p.string ().c_str (), &s) != 0)
- {
- if (errno == ENOENT || errno == ENOTDIR)
- return false;
- else
- throw system_error (errno, system_category ());
- }
-
- return S_ISREG (s.st_mode);
- }
-
- mkdir_status
- try_mkdir (const path& p, mode_t m)
- {
- mkdir_status r (mkdir_status::success);
-
- if (::mkdir (p.string ().c_str (), m) != 0)
- {
- int e (errno);
-
- // EEXIST means the path already exists but not necessarily as
- // a directory.
- //
- if (e == EEXIST && dir_exists (p))
- return mkdir_status::already_exists;
- else
- throw system_error (e, system_category ());
- }
-
- return r;
- }
-
- rmdir_status
- try_rmdir (const path& p)
- {
- rmdir_status r (rmdir_status::success);
-
- if (::rmdir (p.string ().c_str ()) != 0)
- {
- if (errno == ENOENT)
- r = rmdir_status::not_exist;
- else if (errno == ENOTEMPTY || errno == EEXIST)
- r = rmdir_status::not_empty;
- else
- throw system_error (errno, system_category ());
- }
-
- return r;
- }
-
- rmfile_status
- try_rmfile (const path& p)
- {
- rmfile_status r (rmfile_status::success);
-
- if (::unlink (p.string ().c_str ()) != 0)
- {
- if (errno == ENOENT || errno == ENOTDIR)
- r = rmfile_status::not_exist;
- else
- throw system_error (errno, system_category ());
- }
-
- return r;
- }
-}
diff --git a/build/name b/build/name
index 412abad..924c123 100644
--- a/build/name
+++ b/build/name
@@ -10,10 +10,14 @@
#include <iosfwd>
#include <utility> // move()
-#include <build/path>
+#include <butl/path>
+// Note: include <build/types> instead of this file directly.
+//
namespace build
{
+ using butl::dir_path;
+
// A name is what we operate on by default. Depending on the context,
// it can be interpreted as a target or prerequisite name. A name
// without a type and directory can be used to represent any text.
diff --git a/build/operation b/build/operation
index 7492050..51c9f88 100644
--- a/build/operation
+++ b/build/operation
@@ -11,7 +11,7 @@
#include <cstdint>
#include <functional> // reference_wrapper
-#include <build/path>
+#include <build/types>
#include <build/string-table>
namespace build
diff --git a/build/parser b/build/parser
index 35b2f32..403fbaf 100644
--- a/build/parser
+++ b/build/parser
@@ -9,9 +9,8 @@
#include <iosfwd>
#include <utility> // move()
-#include <build/path>
+#include <build/types>
#include <build/token>
-#include <build/name>
#include <build/spec>
#include <build/variable> // list_value
#include <build/diagnostics>
diff --git a/build/path b/build/path
deleted file mode 100644
index f107391..0000000
--- a/build/path
+++ /dev/null
@@ -1,553 +0,0 @@
-// file : build/path -*- C++ -*-
-// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#ifndef BUILD_PATH
-#define BUILD_PATH
-
-#include <string>
-#include <cstddef> // ptrdiff_t
-#include <ostream>
-#include <utility> // move
-#include <iterator>
-#include <exception>
-#include <functional> // hash
-
-namespace build
-{
- template <typename C>
- struct path_traits
- {
- typedef std::basic_string<C> string_type;
- typedef typename string_type::size_type size_type;
-
- // Canonical directory and path seperators.
- //
-#ifdef _WIN32
- static C const directory_separator = '\\';
- static C const path_separator = ';';
-#else
- static C const directory_separator = '/';
- static C const path_separator = ':';
-#endif
-
- // Directory separator tests. On some platforms there
- // could be multiple seperators. For example, on Windows
- // we check for both '/' and '\'.
- //
- static bool
- is_separator (C c)
- {
-#ifdef _WIN32
- return c == '\\' || c == '/';
-#else
- return c == '/';
-#endif
- }
-
- static size_type
- find_separator (string_type const& s, size_type pos = 0)
- {
- for (size_type n (s.size ()); pos < n; ++pos)
- {
- if (is_separator (s[pos]))
- return pos;
- }
-
- return string_type::npos;
- }
-
- static size_type
- rfind_separator (string_type const& s, size_type pos = string_type::npos)
- {
- if (pos == string_type::npos)
- pos = s.size ();
- else
- pos++;
-
- for (; pos > 0; --pos)
- {
- if (is_separator (s[pos - 1]))
- return pos - 1;
- }
-
- return string_type::npos;
- }
-
- // Return the position of '.' or npos if there is no extension.
- //
- static size_type
- find_extension (string_type const& s)
- {
- size_type i (s.size ());
-
- for (; i > 0; --i)
- {
- C c (s[i - 1]);
-
- if (c == '.')
- break;
-
- if (is_separator (c))
- {
- i = 0;
- break;
- }
- }
-
- // Weed out paths like ".txt" (and "/.txt") and "txt.".
- //
- if (i > 1 && !is_separator (s[i - 2]) && i != s.size ())
- return i - 1;
- else
- return string_type::npos;
- }
-
- static int
- compare (string_type const& l, string_type const& r)
- {
- size_type ln (l.size ()), rn (r.size ()), n (ln < rn ? ln : rn);
- for (size_type i (0); i != n; ++i)
- {
-#ifdef _WIN32
- C lc (tolower (l[i])), rc (tolower (r[i]));
-#else
- C lc (l[i]), rc (r[i]);
-#endif
- if (is_separator (lc) && is_separator (rc))
- continue;
-
- if (lc < rc) return -1;
- if (lc > rc) return 1;
- }
-
- return ln < rn ? -1 : (ln > rn ? 1 : 0);
- }
-
- // Get/set current working directory. Throw std::system_error
- // to report the underlying OS errors.
- //
- static string_type
- current ();
-
- static void
- current (string_type const&);
-
- private:
-#ifdef _WIN32
- static C
- tolower (C);
-#endif
- };
-
- template <typename C>
- class invalid_basic_path;
-
- template <typename C, typename K>
- class basic_path;
-
- template <typename C>
- class path_data;
-
- template <typename C>
- struct dir_path_kind;
-
- template <typename C>
- struct any_path_kind
- {
- typedef path_data<C> base_type;
- typedef basic_path<C, dir_path_kind<C>> dir_type;
- };
-
- template <typename C>
- struct dir_path_kind
- {
- typedef basic_path<C, any_path_kind<C>> base_type;
- typedef basic_path<C, dir_path_kind<C>> dir_type;
- };
-
- typedef basic_path<char, any_path_kind<char>> path;
- typedef basic_path<char, dir_path_kind<char>> dir_path;
- typedef invalid_basic_path<char> invalid_path;
-
- typedef basic_path<wchar_t, any_path_kind<wchar_t>> wpath;
- typedef basic_path<wchar_t, dir_path_kind<wchar_t>> dir_wpath;
- typedef invalid_basic_path<wchar_t> invalid_wpath;
-
- //
- //
- class invalid_path_base: std::exception
- {
- public:
- virtual char const*
- what () const throw ();
- };
-
- template <typename C>
- class invalid_basic_path: public invalid_path_base
- {
- public:
- typedef std::basic_string<C> string_type;
-
- invalid_basic_path (C const* p): path_ (p) {}
- invalid_basic_path (string_type const& p): path_ (p) {}
- ~invalid_basic_path () throw () {}
-
- string_type const&
- path () const
- {
- return path_;
- }
-
- private:
- string_type path_;
- };
-
- template <typename C>
- class path_data
- {
- public:
- typedef std::basic_string<C> string_type;
-
- path_data () = default;
-
- explicit
- path_data (string_type s): path_ (std::move (s)) {}
-
- protected:
- string_type path_;
- };
-
- template <typename C, typename K>
- class basic_path: public K::base_type
- {
- public:
- typedef std::basic_string<C> string_type;
- typedef typename string_type::size_type size_type;
-
- typedef typename K::base_type base_type;
- typedef typename K::dir_type dir_type;
-
- typedef path_traits<C> traits;
-
- // Construct special empty path. Note that we have to provide our
- // own implementation rather than using '=default' to make clang
- // allow default-initialized const instances of this type.
- //
- basic_path () {};
-
- explicit
- basic_path (C const* s): base_type (s) {init ();}
-
- basic_path (C const* s, size_type n)
- : base_type (string_type (s, n)) {init ();}
-
- explicit
- basic_path (string_type s): base_type (std::move (s)) {init ();}
-
- basic_path (const string_type& s, size_type n)
- : base_type (string_type (s, 0, n)) {init ();}
-
- basic_path (const string_type& s, size_type p, size_type n)
- : base_type (string_type (s, p, n)) {init ();}
-
- void
- swap (basic_path& p)
- {
- this->path_.swap (p.path_);
- }
-
- void
- clear ()
- {
- this->path_.clear ();
- }
-
- // Get/set current working directory. Throw std::system_error
- // to report the underlying OS errors.
- //
- static dir_type
- current () {return dir_type (traits::current ());}
-
- static void
- current (basic_path const&);
-
- public:
- bool
- empty () const
- {
- return this->path_.empty ();
- }
-
- bool
- absolute () const;
-
- bool
- relative () const
- {
- return !absolute ();
- }
-
- bool
- root () const;
-
- // Return true if *this is a sub-path of the specified path (i.e.,
- // the specified path is a prefix). Expects both paths to be
- // normalized. Note that this function returns true if the paths
- // are equal. Empty path is considered a prefix of any path.
- //
- bool
- sub (const basic_path&) const;
-
- // Return true if *this is a super-path of the specified path (i.e.,
- // the specified path is a suffix). Expects both paths to be
- // normalized. Note that this function returns true if the paths
- // are equal. Empty path is considered a suffix of any path.
- //
- bool
- sup (const basic_path&) const;
-
- public:
- // Return the path without the directory part.
- //
- 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.
- //
- dir_type
- 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.
- //
- dir_type
- directory (basic_path const&) const;
-
- // Return the root directory of the path or empty path if
- // the directory is not absolute.
- //
- dir_type
- root_directory () const;
-
- // Return the path without the extension, if any.
- //
- basic_path
- base () const;
-
- // Return the extension or NULL if not present.
- //
- const C*
- extension () const;
-
- // Return a path relative to the specified path that is equivalent
- // to *this. Throws invalid_path if a relative path cannot be derived
- // (e.g., paths are on different drives on Windows).
- //
- basic_path
- relative (basic_path) const;
-
- // Iteration over path components.
- //
- public:
- struct iterator
- {
- typedef string_type value_type;
- typedef string_type* pointer;
- typedef string_type& reference;
- typedef std::ptrdiff_t difference_type;
- typedef std::forward_iterator_tag iterator_category;
-
- typedef typename string_type::size_type size_type;
-
- iterator (): p_ (nullptr) {}
- iterator (const string_type& p, size_type b, size_type e)
- : p_ (&p), b_ (b), e_ (e) {}
-
- iterator&
- operator++ ()
- {
- b_ = e_;
-
- if (b_ != string_type::npos)
- e_ = traits::find_separator (*p_, ++b_);
-
- return *this;
- }
-
- iterator
- operator++ (int) {iterator r (*this); return ++r;}
-
- string_type operator* () const
- {
- return string_type (*p_, b_, (e_ != string_type::npos ? e_ - b_ : e_));
- }
-
- friend bool
- operator== (const iterator& x, const iterator& y)
- {
- return x.p_ == y.p_ && x.b_ == y.b_ && x.e_ == y.e_;
- }
-
- friend bool
- operator!= (const iterator& x, const iterator& y) {return !(x == y);}
-
- private:
- // b != npos && e == npos - last component
- // b == npos && e == npos - one past last component (end)
- //
- const string_type* p_;
- size_type b_;
- size_type e_;
- };
-
- iterator begin () const;
- iterator end () const;
-
- public:
- // Normalize the path. This includes collapsing the '.' and '..'
- // directories if possible, collapsing multiple directory
- // separators, and converting all directory separators to the
- // canonical form. Returns *this.
- //
- basic_path&
- normalize ();
-
- // Make the path absolute using the current directory unless
- // it is already absolute.
- //
- basic_path&
- complete ();
-
- public:
- basic_path&
- operator/= (basic_path const&);
-
- basic_path
- operator+ (string_type const& s) const
- {
- return basic_path (this->path_ + s);
- }
-
- basic_path
- operator+ (C c) const
- {
- return basic_path (this->path_ + c);
- }
-
- basic_path&
- operator+= (string_type const& s)
- {
- this->path_ += s;
- return *this;
- }
-
- basic_path&
- operator+= (C c)
- {
- this->path_ += c;
- return *this;
- }
-
- // Note that comparison is case-insensitive if the filesystem is
- // not case-sensitive (e.g., Windows).
- //
- bool
- operator== (basic_path const& x) const
- {
- return traits::compare (this->path_, x.path_) == 0;
- }
-
- bool
- operator!= (basic_path const& x) const
- {
- return !(*this == x);
- }
-
- bool
- operator< (basic_path const& x) const
- {
- return traits::compare (this->path_, x.path_) < 0;
- }
-
- public:
- const string_type&
- string () const
- {
- return this->path_;
- }
-
- // If possible, return a POSIX representation of the path. For example,
- // for a Windows path in the form foo\bar this function will return
- // foo/bar. If it is not possible to create a POSIX representation for
- // this path (e.g., c:\foo), this function will throw the invalid_path
- // exception.
- //
- string_type
- posix_string () const;
-
- private:
- void
- init ();
- };
-
- template <typename C, typename K>
- inline basic_path<C, K>
- operator/ (basic_path<C, K> const& x, basic_path<C, K> const& y)
- {
- basic_path<C, K> r (x);
- r /= y;
- return r;
- }
-
- // Additional operators for certain path kind combinations.
- //
- template <typename C>
- inline basic_path<C, any_path_kind<C>>
- operator/ (basic_path<C, dir_path_kind<C>> const& x,
- basic_path<C, any_path_kind<C>> const& y)
- {
- basic_path<C, any_path_kind<C>> r (x);
- r /= y;
- return r;
- }
-
- // IO
- //
-
- /*
- template <typename C, typename K>
- inline std::basic_ostream<C>&
- operator<< (std::basic_ostream<C>& os, basic_path<C, K> const& p)
- {
- return os << p.string ();
- }
- */
-}
-
-namespace std
-{
- template <typename C, typename K>
- struct hash<build::basic_path<C, K>>: hash<basic_string<C>>
- {
- size_t
- operator() (const build::basic_path<C, K>& p) const noexcept
- {
- return hash<basic_string<C>>::operator() (p.string ());
- }
- };
-}
-
-#include <build/path.ixx>
-#include <build/path.txx>
-
-#endif // BUILD_PATH
diff --git a/build/path-io b/build/path-io
index c2130da..888a8b4 100644
--- a/build/path-io
+++ b/build/path-io
@@ -7,10 +7,15 @@
#include <iosfwd>
-#include <build/path>
+#include <butl/path>
+// Custom path IO.
+//
namespace build
{
+ using butl::path;
+ using butl::dir_path;
+
std::ostream&
operator<< (std::ostream&, const path&);
diff --git a/build/path-map b/build/path-map
deleted file mode 100644
index 8355ccc..0000000
--- a/build/path-map
+++ /dev/null
@@ -1,88 +0,0 @@
-// file : build/path-map -*- C++ -*-
-// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#ifndef BUILD_PATH_MAP
-#define BUILD_PATH_MAP
-
-#include <butl/prefix-map>
-
-#include <build/path>
-
-namespace butl
-{
-
- // @@ Remove butl:: when move to libbutl.
-
- // prefix_map for paths
- //
- // The paths should be normalized.
- //
- // Note that the path's representation of POSIX root ('/') is
- // inconsistent in that we have a trailing delimiter at the end of
- // the path (its "proper" representation would have been an empty
- // string but that would have clashed with empty paths). To work
- // around this snag, this implementation, during key comparison,
- // detects '/' and treats it as empty. Note that the map will
- // still store the key as you have first inserted it. So if you
- // want a particular representation, pre-populate the map with
- // it.
- //
- template <typename C, typename K>
- struct compare_prefix<build::basic_path<C, K>>: compare_prefix<std::basic_string<C>>
- {
- typedef build::basic_path<C, K> key_type;
-
- typedef C delimiter_type;
- typedef std::basic_string<C> string_type;
- typedef compare_prefix<std::basic_string<C>> base;
-
- explicit
- compare_prefix (delimiter_type d): base (d) {}
-
- bool
- operator() (const key_type& x, const key_type& y) const
- {
- const auto& xs (x.string ());
- const auto& ys (y.string ());
-
-#ifdef _WIN32
- return base::compare (xs.c_str (),
- xs.size (),
- ys.c_str (),
- ys.size ()) < 0;
-#else
- return base::compare (xs.c_str (),
- x.root () ? 0 : xs.size (),
- ys.c_str (),
- y.root () ? 0 : ys.size ()) < 0;
-#endif
- }
-
- bool
- prefix (const key_type& p, const key_type& k) const
- {
- const auto& ps (p.string ());
- const auto& ks (k.string ());
-
-#ifdef _WIN32
- return base::prefix (ps, ks);
-#else
- return base::prefix (p.root () ? string_type () : ps,
- k.root () ? string_type () : ks);
-#endif
- }
- };
-}
-
-namespace build
-{
- template <typename T>
- using path_map = butl::prefix_map<path, T, path::traits::directory_separator>;
-
- template <typename T>
- using dir_path_map =
- butl::prefix_map<dir_path, T, dir_path::traits::directory_separator>;
-}
-
-#endif // BUILD_PATH_MAP
diff --git a/build/path.cxx b/build/path.cxx
deleted file mode 100644
index 3a3ea3d..0000000
--- a/build/path.cxx
+++ /dev/null
@@ -1,109 +0,0 @@
-// file : build/path.cxx -*- C++ -*-
-// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#include <build/path>
-
-#ifdef _WIN32
-# include <stdlib.h> // _MAX_PATH
-# include <direct.h> // _[w]getcwd, _[w]chdir
-#else
-# include <errno.h> // EINVAL
-# include <stdlib.h> // mbstowcs, wcstombs
-# include <limits.h> // PATH_MAX
-# include <unistd.h> // getcwd, chdir
-#endif
-
-#include <system_error>
-
-using namespace std;
-
-namespace build
-{
- char const* invalid_path_base::
- what () const throw ()
- {
- return "invalid filesystem path";
- }
-
- //
- // char
- //
-
- template <>
- path_traits<char>::string_type path_traits<char>::
- current ()
- {
- // @@ throw system_error (and in the other current() versions).
-
-#ifdef _WIN32
- char cwd[_MAX_PATH];
- if(_getcwd(cwd, _MAX_PATH) == 0)
- throw system_error (errno, system_category ());
-#else
- char cwd[PATH_MAX];
- if (getcwd (cwd, PATH_MAX) == 0)
- throw system_error (errno, system_category ());
-#endif
-
- return string_type (cwd);
- }
-
- template <>
- void path_traits<char>::
- current (string_type const& s)
- {
-#ifdef _WIN32
- if(_chdir(s.c_str ()) != 0)
- throw system_error (errno, system_category ());
-#else
- if (chdir (s.c_str ()) != 0)
- throw system_error (errno, system_category ());
-#endif
- }
-
- //
- // wchar_t
- //
-
- template <>
- path_traits<wchar_t>::string_type path_traits<wchar_t>::
- current ()
- {
-#ifdef _WIN32
- wchar_t wcwd[_MAX_PATH];
- if(_wgetcwd(wcwd, _MAX_PATH) == 0)
- throw system_error (errno, system_category ());
-#else
- char cwd[PATH_MAX];
- if (getcwd (cwd, PATH_MAX) == 0)
- throw system_error (errno, system_category ());
-
- wchar_t wcwd[PATH_MAX];
- if (mbstowcs (wcwd, cwd, PATH_MAX) == size_type (-1))
- throw system_error (EINVAL, system_category ());
-#endif
-
- return string_type (wcwd);
- }
-
- template <>
- void path_traits<wchar_t>::
- current (string_type const& s)
- {
-#ifdef _WIN32
- if(_wchdir(s.c_str ()) != 0)
- throw system_error (errno, system_category ());
-#else
- char ns[PATH_MAX + 1];
-
- if (wcstombs (ns, s.c_str (), PATH_MAX) == size_type (-1))
- throw system_error (EINVAL, system_category ());
-
- ns[PATH_MAX] = '\0';
-
- if (chdir (ns) != 0)
- throw system_error (errno, system_category ());
-#endif
- }
-}
diff --git a/build/path.ixx b/build/path.ixx
deleted file mode 100644
index 9193fba..0000000
--- a/build/path.ixx
+++ /dev/null
@@ -1,171 +0,0 @@
-// file : build/path.ixx -*- C++ -*-
-// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#ifdef _WIN32
-# include <cctype> // std::tolower
-# include <cwctype> // std::towlower
-#endif
-
-namespace build
-{
-#ifdef _WIN32
- template <>
- inline char path_traits<char>::
- tolower (char c)
- {
- return std::tolower (c);
- }
-
- template <>
- inline wchar_t path_traits<wchar_t>::
- tolower (wchar_t c)
- {
- return std::towlower (c);
- }
-#endif
-
- template <typename C, typename K>
- inline bool basic_path<C, K>::
- absolute () const
- {
-#ifdef _WIN32
- return this->path_.size () > 1 && this->path_[1] == ':';
-#else
- return !this->path_.empty () && traits::is_separator (this->path_[0]);
-#endif
- }
-
- template <typename C, typename K>
- inline bool basic_path<C, K>::
- root () const
- {
-#ifdef _WIN32
- return this->path_.size () == 2 && this->path_[1] == ':';
-#else
- return this->path_.size () == 1 && traits::is_separator (this->path_[0]);
-#endif
- }
-
- template <typename C, typename K>
- inline bool basic_path<C, K>::
- sub (const basic_path& p) const
- {
- size_type n (p.path_.size ());
-
- if (n == 0)
- return true;
-
- size_type m (this->path_.size ());
-
- // The second condition guards against the /foo-bar vs /foo case.
- //
- return m >= n && this->path_.compare (0, n, p.path_) == 0 &&
- (traits::is_separator (p.path_.back ()) || // p ends with a separator
- m == n || // *this == p
- traits::is_separator (this->path_[n])); // next char is a separator
- }
-
- template <typename C, typename K>
- inline bool basic_path<C, K>::
- sup (const basic_path& p) const
- {
- size_type n (p.path_.size ());
-
- if (n == 0)
- return true;
-
- size_type m (this->path_.size ());
-
- // The second condition guards against the /foo-bar vs bar case.
- //
- return m >= n && this->path_.compare (m - n, n, p.path_) == 0 &&
- (m == n || // *this == p
- traits::is_separator (this->path_[m - n - 1])); // prev char separator
- }
-
- template <typename C, typename K>
- inline auto basic_path<C, K>::
- begin () const -> iterator
- {
- size_type b, e;
-
- if (this->path_.empty ())
- b = e = string_type::npos;
-
-#ifndef _WIN32
- else if (root ())
- {
- // We want to return a single empty component. Here we return
- // the begin position one past the end. Not sure if this legal.
- //
- b = 1;
- e = string_type::npos;
- }
-#endif
- else
- {
- b = 0;
- e = traits::find_separator (this->path_);
- }
-
- return iterator (this->path_, b, e);
- }
-
- template <typename C, typename K>
- inline auto basic_path<C, K>::
- end () const -> iterator
- {
- return iterator (this->path_, string_type::npos, string_type::npos);
- }
-
- template <typename C, typename K>
- inline basic_path<C, K>& basic_path<C, K>::
- complete ()
- {
- if (relative ())
- *this = current () / *this;
-
- return *this;
- }
-
- template <typename C, typename K>
- inline typename basic_path<C, K>::dir_type basic_path<C, K>::
- root_directory () const
- {
- return absolute ()
-#ifdef _WIN32
- ? dir_type (this->path_, 2)
-#else
- ? dir_type ("/")
-#endif
- : dir_type ();
- }
-
- template <typename C, typename K>
- inline basic_path<C, K> basic_path<C, K>::
- base () const
- {
- size_type p (traits::find_extension (this->path_));
- return p != string_type::npos
- ? basic_path (this->path_.c_str (), p)
- : *this;
- }
-
- template <typename C, typename K>
- inline const C* basic_path<C, K>::
- extension () const
- {
- size_type p (traits::find_extension (this->path_));
- return p != string_type::npos ? this->path_.c_str () + p + 1 : nullptr;
- }
-
-#ifndef _WIN32
- template <typename C, typename K>
- inline typename basic_path<C, K>::string_type basic_path<C, K>::
- posix_string () const
- {
- return string ();
- }
-#endif
-}
diff --git a/build/path.txx b/build/path.txx
deleted file mode 100644
index c664eaf..0000000
--- a/build/path.txx
+++ /dev/null
@@ -1,256 +0,0 @@
-// file : build/path.txx -*- C++ -*-
-// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#include <vector>
-
-namespace build
-{
- template <typename C, typename K>
- basic_path<C, K> basic_path<C, K>::
- leaf () const
- {
- size_type p (traits::rfind_separator (this->path_));
-
- return p != string_type::npos
- ? basic_path (this->path_.c_str () + p + 1, this->path_.size () - p - 1)
- : *this;
- }
-
- template <typename C, typename K>
- typename basic_path<C, K>::dir_type basic_path<C, K>::
- directory () const
- {
- if (root ())
- return dir_type ();
-
- size_type p (traits::rfind_separator (this->path_));
-
- // Include the trailing slash so that we get correct behavior
- // if directory is root.
- //
- return p != string_type::npos
- ? dir_type (this->path_.c_str (), p + 1)
- : dir_type ();
- }
-
-#ifdef _WIN32
- template <typename C, typename K>
- typename basic_path<C, K>::string_type basic_path<C, K>::
- posix_string () const
- {
- if (absolute ())
- throw invalid_basic_path<C> (this->path_);
-
- string_type r (this->path_);
-
- // Translate Windows-style separators to the POSIX ones.
- //
- for (size_type i (0), n (r.size ()); i != n; ++i)
- if (r[i] == '\\')
- r[i] = '/';
-
- return r;
- }
-#endif
-
- template <typename C, typename K>
- basic_path<C, K>& basic_path<C, K>::
- operator/= (basic_path<C, K> const& r)
- {
- if (r.absolute () && !this->path_.empty ()) // Allow ('' / '/foo').
- throw invalid_basic_path<C> (r.path_);
-
- if (this->path_.empty () || r.path_.empty ())
- {
- this->path_ += r.path_;
- return *this;
- }
-
- if (!traits::is_separator (this->path_[this->path_.size () - 1]))
- this->path_ += traits::directory_separator;
-
- this->path_ += r.path_;
- return *this;
- }
-
- template <typename C, typename K>
- basic_path<C, K> basic_path<C, K>::
- leaf (basic_path<C, K> const& d) const
- {
- size_type n (d.path_.size ());
-
- if (n == 0)
- return *this;
-
- if (!sub (d))
- throw invalid_basic_path<C> (this->path_);
-
- size_type m (this->path_.size ());
-
- if (n != m
-#ifndef _WIN32
- && !d.root ()
-#endif
- )
- n++; // Skip the directory separator (unless it is POSIX root).
-
- return basic_path (this->path_.c_str () + n, m - n);
- }
-
- template <typename C, typename K>
- typename basic_path<C, K>::dir_type basic_path<C, K>::
- directory (basic_path<C, K> const& l) const
- {
- size_type n (l.path_.size ());
-
- if (n == 0)
- return dir_type (this->path_);
-
- if (!sup (l))
- throw invalid_basic_path<C> (this->path_);
-
- size_type m (this->path_.size ());
-
- if (n != m)
- n++; // Skip the directory separator.
-
- return dir_type (this->path_.c_str (), m - n);
- }
-
- template <typename C, typename K>
- basic_path<C, K> basic_path<C, K>::
- relative (basic_path<C, K> d) const
- {
- basic_path r;
-
- for (;; d = d.directory ())
- {
- if (sub (d))
- break;
-
- r /= basic_path ("..");
-
- // Roots of the paths do not match.
- //
- if (d.root ())
- throw invalid_basic_path<C> (this->path_);
- }
-
- return r / leaf (d);
- }
-
- template <typename C, typename K>
- basic_path<C, K>& basic_path<C, K>::
- normalize ()
- {
- if (empty ())
- return *this;
-
- bool abs (absolute ());
-
- typedef std::vector<string_type> paths;
- paths ps;
-
- for (size_type b (0), e (traits::find_separator (this->path_)),
- n (this->path_.size ());;
- e = traits::find_separator (this->path_, b))
- {
- string_type s (this->path_, b, e == string_type::npos ? e : e - b);
- ps.push_back (s);
-
- if (e == string_type::npos)
- break;
-
- ++e;
-
- while (e < n && traits::is_separator (this->path_[e]))
- ++e;
-
- if (e == n)
- break;
-
- b = e;
- }
-
- // First collapse '.' and '..'.
- //
- paths r;
-
- for (typename paths::const_iterator i (ps.begin ()), e (ps.end ());
- i != e; ++i)
- {
- string_type const& s (*i);
- size_type n (s.size ());
-
- if (n == 1 && s[0] == '.')
- continue;
-
- if (n == 2 && s[0] == '.' && s[1] == '.')
- {
- // Pop the last directory from r unless it is '..'.
- //
- if (!r.empty ())
- {
- string_type const& s1 (r.back ());
-
- if (!(s1.size () == 2 && s1[0] == '.' && s1[1] == '.'))
- {
- // Cannot go past the root directory.
- //
- if (abs && r.size () == 1)
- throw invalid_basic_path<C> (this->path_);
-
- r.pop_back ();
- continue;
- }
- }
- }
-
- r.push_back (s);
- }
-
- // Reassemble the path.
- //
- string_type p;
-
- for (typename paths::const_iterator i (r.begin ()), e (r.end ());
- i != e;)
- {
- p += *i;
-
- if (++i != e)
- p += traits::directory_separator;
- }
-
- if (p.empty () && !r.empty ())
- p += traits::directory_separator; // Root directory.
-
- this->path_.swap (p);
- return *this;
- }
-
- template <typename C, typename K>
- void basic_path<C, K>::
- current (basic_path const& p)
- {
- const string_type& s (p.string ());
-
- if (s.empty ())
- throw invalid_basic_path<char> (s);
-
- traits::current (s);
- }
-
- template <typename C, typename K>
- void basic_path<C, K>::
- init ()
- {
- // Strip trailing slashes except for the case where the single
- // slash represents the root directory.
- //
- size_type n (this->path_.size ());
- for (; n > 1 && traits::is_separator (this->path_[n - 1]); --n) ;
- this->path_.resize (n);
- }
-}
diff --git a/build/prerequisite b/build/prerequisite
index ba850ec..0d3428f 100644
--- a/build/prerequisite
+++ b/build/prerequisite
@@ -13,7 +13,7 @@
#include <typeindex>
#include <functional> // reference_wrapper
-#include <build/path>
+#include <build/types>
#include <build/target-key>
#include <build/utility> // extension_pool
#include <build/diagnostics>
diff --git a/build/rule b/build/rule
index 04d3650..c7134e1 100644
--- a/build/rule
+++ b/build/rule
@@ -12,6 +12,7 @@
#include <butl/prefix-map>
+#include <build/types>
#include <build/target>
#include <build/operation>
diff --git a/build/rule.cxx b/build/rule.cxx
index a99611b..b3dfaeb 100644
--- a/build/rule.cxx
+++ b/build/rule.cxx
@@ -7,14 +7,15 @@
#include <utility> // move()
#include <system_error>
+#include <butl/filesystem>
+
#include <build/scope>
#include <build/algorithm>
#include <build/diagnostics>
-#include <build/timestamp>
-#include <build/filesystem>
#include <build/context>
using namespace std;
+using namespace butl;
namespace build
{
diff --git a/build/scope b/build/scope
index 7dec7a2..5266370 100644
--- a/build/scope
+++ b/build/scope
@@ -9,8 +9,9 @@
#include <unordered_set>
#include <unordered_map>
-#include <build/path>
-#include <build/path-map>
+#include <butl/path-map>
+
+#include <build/types>
#include <build/variable>
#include <build/prerequisite>
#include <build/operation>
@@ -133,7 +134,8 @@ namespace build
temp_scope (scope& p) {path_ = p.path_; parent_ = &p; root_ = p.root_;}
};
- class scope_map: public dir_path_map<scope>
+ using scope_map_base = butl::dir_path_map<scope>;
+ class scope_map: public scope_map_base
{
public:
// Note that we assume the first insertion into the map is that
@@ -160,9 +162,6 @@ namespace build
//
return find (dir_path (p.string ()));
}
-
- private:
- typedef dir_path_map<scope> base;
};
extern scope_map scopes;
diff --git a/build/scope.cxx b/build/scope.cxx
index 2b24702..5bd2b62 100644
--- a/build/scope.cxx
+++ b/build/scope.cxx
@@ -119,14 +119,14 @@ namespace build
// Normally we would have a scope for the full path so try
// that before making any copies.
//
- auto i (base::find (k));
+ auto i (scope_map_base::find (k));
if (i != end ())
return i->second;
for (dir_path d (k.directory ());; d = d.directory ())
{
- auto i (base::find (d));
+ auto i (scope_map_base::find (d));
if (i != end ())
return i->second;
diff --git a/build/search.cxx b/build/search.cxx
index dc59a9b..ee6e20f 100644
--- a/build/search.cxx
+++ b/build/search.cxx
@@ -4,17 +4,16 @@
#include <build/search>
-#include <utility> // move
+#include <utility> // move()
#include <cassert>
-#include <build/path>
#include <build/scope>
#include <build/target>
#include <build/prerequisite>
-#include <build/timestamp>
#include <build/diagnostics>
using namespace std;
+using namespace butl;
namespace build
{
diff --git a/build/spec b/build/spec
index bdfda4c..f50110b 100644
--- a/build/spec
+++ b/build/spec
@@ -10,8 +10,7 @@
#include <iosfwd>
#include <utility> // move()
-#include <build/path>
-#include <build/name>
+#include <build/types>
namespace build
{
diff --git a/build/target b/build/target
index d12a8e5..9388065 100644
--- a/build/target
+++ b/build/target
@@ -19,9 +19,7 @@
#include <butl/utility> // compare_c_string
#include <butl/multi-index> // map_iterator_adapter
-#include <build/path>
-#include <build/timestamp>
-#include <build/name>
+#include <build/types>
#include <build/variable>
#include <build/operation>
#include <build/target-key>
diff --git a/build/target-key b/build/target-key
index 2fa2186..9e74c27 100644
--- a/build/target-key
+++ b/build/target-key
@@ -9,7 +9,7 @@
#include <typeindex>
#include <ostream>
-#include <build/path>
+#include <build/types>
namespace build
{
diff --git a/build/timestamp b/build/timestamp
deleted file mode 100644
index 3479a77..0000000
--- a/build/timestamp
+++ /dev/null
@@ -1,54 +0,0 @@
-// file : build/timestamp -*- C++ -*-
-// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#ifndef BUILD_TIMESTAMP
-#define BUILD_TIMESTAMP
-
-#include <chrono>
-#include <string>
-#include <iosfwd>
-
-#include <build/path>
-
-namespace build
-{
- // On all three main platforms that we target (GNU/Linux, Windows (both
- // VC++ and GCC/MinGW64), and MacOS X) with recent C++ runtimes,
- // system_clock has nanoseconds resolution and counts from the UNIX
- // epoch. The latter is important since struct stat also returns times
- // based on UNIX epoch.
- //
- // The underlying type for nanoseconds duration is signed integer type
- // of at least 64 bits (currently int64_t). Because it is signed, we
- // will overflow in year 2262 but by then the underlying type will
- // most likely have changed to something larger than 64-bit.
- //
- // So to support other platforms that could possibly use a different
- // system_clock resolutions (e.g., microseconds), we actually not going
- // to assume anywhere (except perhaps timestamp.cxx) that we are dealing
- // with nanoseconds or the 64-bit underlying type.
- //
- using std::chrono::system_clock;
-
- using timestamp = system_clock::time_point;
- using duration = system_clock::duration;
-
- const timestamp timestamp_unknown {duration {-1}};
- const timestamp timestamp_nonexistent {duration {0}};
-
- std::ostream&
- operator<< (std::ostream&, const timestamp&);
-
- std::ostream&
- operator<< (std::ostream&, const duration&);
-
- // Returns timestamp_nonexistent if the entry at the specified path
- // does not exist. All other errors are reported by throwing
- // std::system_error.
- //
- timestamp
- path_mtime (const path&);
-};
-
-#endif // BUILD_TIMESTAMP
diff --git a/build/timestamp.cxx b/build/timestamp.cxx
deleted file mode 100644
index 9d6e70c..0000000
--- a/build/timestamp.cxx
+++ /dev/null
@@ -1,177 +0,0 @@
-// file : build/timestamp.cxx -*- C++ -*-
-// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#include <build/timestamp>
-
-#include <unistd.h> // stat
-#include <sys/types.h> // stat
-#include <sys/stat.h> // stat
-
-#include <time.h> // localtime, gmtime, strftime
-
-#include <ostream>
-#include <system_error>
-
-using namespace std;
-
-namespace build
-{
- // Figuring out whether we have the nanoseconds in some form.
- //
- template <typename S>
- constexpr auto nsec (const S* s) -> decltype(s->st_mtim.tv_nsec)
- {
- return s->st_mtim.tv_nsec; // POSIX (GNU/Linux, Solaris).
- }
-
- template <typename S>
- constexpr auto nsec (const S* s) -> decltype(s->st_mtimespec.tv_nsec)
- {
- return s->st_mtimespec.tv_nsec; // MacOS X.
- }
-
- template <typename S>
- constexpr auto nsec (const S* s) -> decltype(s->st_mtime_n)
- {
- return s->st_mtime_n; // AIX 5.2 and later.
- }
-
- template <typename S>
- constexpr int nsec (...) {return 0;}
-
- timestamp
- path_mtime (const path& p)
- {
- struct stat s;
- if (stat (p.string ().c_str (), &s) != 0)
- {
- if (errno == ENOENT || errno == ENOTDIR)
- return timestamp_nonexistent;
- else
- throw system_error (errno, system_category ());
- }
-
- return system_clock::from_time_t (s.st_mtime) +
- chrono::duration_cast<duration> (
- chrono::nanoseconds (nsec<struct stat> (&s)));
- }
-
- ostream&
- operator<< (ostream& os, const timestamp& ts)
- {
- // @@ replace with put_time()
- //
-
- time_t t (system_clock::to_time_t (ts));
-
- if (t == 0)
- return os << "<nonexistent>";
-
- std::tm tm;
- if (localtime_r (&t, &tm) == nullptr)
- throw system_error (errno, system_category ());
-
- // If year is greater than 9999, we will overflow.
- //
- char buf[20]; // YYYY-MM-DD HH:MM:SS\0
- if (strftime (buf, sizeof (buf), "%Y-%m-%d %H:%M:%S", &tm) == 0)
- return os << "<beyond year 9999>";
-
- os << buf;
-
- using namespace chrono;
-
- timestamp sec (system_clock::from_time_t (t));
- nanoseconds ns (duration_cast<nanoseconds> (ts - sec));
-
- if (ns != nanoseconds::zero ())
- {
- os << '.';
- os.width (9);
- os.fill ('0');
- os << ns.count ();
- }
-
- return os;
- }
-
- ostream&
- operator<< (ostream& os, const duration& d)
- {
- // @@ replace with put_time()
- //
-
- timestamp ts; // Epoch.
- ts += d;
-
- time_t t (system_clock::to_time_t (ts));
-
- const char* fmt (nullptr);
- const char* unt ("nanoseconds");
- if (t >= 365 * 12 * 24 * 60 * 60)
- {
- fmt = "%Y-%m-%d %H:%M:%S";
- unt = "years";
- }
- else if (t >= 12 * 24 * 60* 60)
- {
- fmt = "%m-%d %H:%M:%S";
- unt = "months";
- }
- else if (t >= 24 * 60* 60)
- {
- fmt = "%d %H:%M:%S";
- unt = "days";
- }
- else if (t >= 60 * 60)
- {
- fmt = "%H:%M:%S";
- unt = "hours";
- }
- else if (t >= 60)
- {
- fmt = "%M:%S";
- unt = "minutes";
- }
- else if (t >= 1)
- {
- fmt = "%S";
- unt = "seconds";
- }
-
- if (fmt != nullptr)
- {
- std::tm tm;
- if (gmtime_r (&t, &tm) == nullptr)
- throw system_error (errno, system_category ());
-
- char buf[20]; // YYYY-MM-DD HH:MM:SS\0
- if (strftime (buf, sizeof (buf), fmt, &tm) == 0)
- return os << "<beyond 9999>";
-
- os << buf;
- }
-
- using namespace chrono;
-
- timestamp sec (system_clock::from_time_t (t));
- nanoseconds ns (duration_cast<nanoseconds> (ts - sec));
-
- if (ns != nanoseconds::zero ())
- {
- if (fmt != nullptr)
- {
- os << '.';
- os.width (9);
- os.fill ('0');
- }
-
- os << ns.count () << ' ' << unt;
- }
- else if (fmt == 0)
- os << '0';
-
- return os;
- }
-}
diff --git a/build/types b/build/types
index c29890a..5f6b3de 100644
--- a/build/types
+++ b/build/types
@@ -7,13 +7,32 @@
#include <vector>
-#include <build/path>
+#include <butl/path>
+#include <butl/timestamp>
+
+#include <build/name>
namespace build
{
// Commonly-used types.
//
+ // <butl/path>
+ //
+ using butl::path;
+ using butl::dir_path;
+ using butl::basic_path;
+ using butl::invalid_path;
+
+ // <butl/timestamp>
+ //
+ using butl::system_clock;
+ using butl::timestamp;
+ using butl::duration;
+ using butl::timestamp_unknown;
+ using butl::timestamp_nonexistent;
+ using butl::operator<<;
+
typedef std::vector<path> paths;
typedef std::vector<dir_path> dir_paths;
}
diff --git a/build/utility b/build/utility
index 717a9ed..4135b37 100644
--- a/build/utility
+++ b/build/utility
@@ -11,7 +11,7 @@
#include <exception>
#include <unordered_set>
-#include <build/path>
+#include <build/types>
namespace build
{
diff --git a/build/variable b/build/variable
index 42f0787..2164f92 100644
--- a/build/variable
+++ b/build/variable
@@ -16,8 +16,7 @@
#include <butl/prefix-map>
-#include <build/path>
-#include <build/name>
+#include <build/types>
namespace build
{
diff --git a/tests/build/buildfile b/tests/build/buildfile
index 19ea46e..8d7e692 100644
--- a/tests/build/buildfile
+++ b/tests/build/buildfile
@@ -1,4 +1,3 @@
-d=path/
-
+d=
.: $d
include $d
diff --git a/tests/build/parser/driver.cxx b/tests/build/parser/driver.cxx
index 57d9267..fef2f41 100644
--- a/tests/build/parser/driver.cxx
+++ b/tests/build/parser/driver.cxx
@@ -6,7 +6,7 @@
#include <sstream>
#include <iostream>
-#include <build/path>
+#include <build/types>
#include <build/scope>
#include <build/target>
#include <build/native>
diff --git a/tests/build/path/buildfile b/tests/build/path/buildfile
deleted file mode 100644
index c2756b7..0000000
--- a/tests/build/path/buildfile
+++ /dev/null
@@ -1 +0,0 @@
-exe{driver}: cxx{driver ../../../build/path}
diff --git a/tests/build/path/driver.cxx b/tests/build/path/driver.cxx
deleted file mode 100644
index 58839d4..0000000
--- a/tests/build/path/driver.cxx
+++ /dev/null
@@ -1,227 +0,0 @@
-// file : tests/build/path/driver.cxx -*- C++ -*-
-// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#include <cassert>
-#include <iostream>
-
-#include <build/path>
-
-using namespace std;
-using namespace build;
-
-int
-main ()
-{
- assert (path ("/").string () == "/");
- assert (path ("//").string () == "/");
- assert (path ("/tmp/foo/").string () == "/tmp/foo");
-#ifdef _WIN32
- assert (path ("\\\\").string () == "\\");
- assert (path ("/\\").string () == "/");
- assert (path ("C:").string () == "C:");
- assert (path ("C:\\").string () == "C:");
- assert (path ("C:\\tmp\\foo\\").string () == "C:\\tmp\\foo");
-#endif
-
- // abslote/relative/root
- //
-#ifndef _WIN32
- assert (path ("/").root ());
- assert (path ("//").root ());
- assert (path ("/").absolute ());
- assert (path ("/foo/bar").absolute ());
- assert (path ("bar/baz").relative ());
-#else
- assert (path ("C:").root ());
- assert (path ("C:\\").root ());
- assert (path ("C:\\").absolute ());
- assert (path ("C:\\foo\\bar").absolute ());
- assert (path ("bar\\baz").relative ());
-#endif
-
-
- // leaf
- //
-#ifndef _WIN32
- assert (path ("/").leaf ().string () == "");
- assert (path ("/tmp").leaf ().string () == "tmp");
- assert (path ("//tmp").leaf ().string () == "tmp");
-#else
- assert (path ("C:").leaf ().string () == "C:");
- assert (path ("C:\\tmp").leaf ().string () == "tmp");
- assert (path ("C:\\\\tmp").leaf ().string () == "tmp");
-#endif
-
- // directory
- //
-#ifndef _WIN32
- assert (path ("/").directory ().string () == "");
- assert (path ("/tmp").directory ().string () == "/");
- assert (path ("//tmp").directory ().string () == "/");
-#else
- assert (path ("C:").directory ().string () == "");
- assert (path ("C:\\tmp").directory ().string () == "C:");
- assert (path ("C:\\\\tmp").directory ().string () == "C:");
-#endif
-
- // base
- //
- assert (path ("/").base ().string () == "/");
- assert (path ("/foo.txt").base ().string () == "/foo");
- assert (path (".txt").base ().string () == ".txt");
- assert (path ("/.txt").base ().string () == "/.txt");
- assert (path ("foo.txt.orig").base ().string () == "foo.txt");
-#ifdef _WIN32
- assert (path ("C:").base ().string () == "C:");
- assert (path ("C:\\foo.txt").base ().string () == "C:\\foo");
-#endif
-
- // iteration
- //
- {
- path p;
- assert (p.begin () == p.end ());
- }
- {
- path p ("foo");
- path::iterator i (p.begin ());
- assert (i != p.end () && *i == "foo");
- assert (++i == p.end ());
- }
- {
- path p ("foo/bar");
- path::iterator i (p.begin ());
- assert (i != p.end () && *i == "foo");
- assert (++i != p.end () && *i == "bar");
- assert (++i == p.end ());
- }
- {
- path p ("/foo/bar");
- path::iterator i (p.begin ());
- assert (i != p.end () && *i == "");
- assert (++i != p.end () && *i == "foo");
- assert (++i != p.end () && *i == "bar");
- assert (++i == p.end ());
- }
- {
- path p ("/");
- path::iterator i (p.begin ());
- assert (i != p.end () && *i == "");
- assert (++i == p.end ());
- }
-
- // operator/
- //
-#ifndef _WIN32
- assert ((path ("/") / path ("tmp")).string () == "/tmp");
- assert ((path ("foo") / path ("bar")).string () == "foo/bar");
-#else
- assert ((path ("\\") / path ("tmp")).string () == "\\tmp");
- assert ((path ("C:\\") / path ("tmp")).string () == "C:\\tmp");
- assert ((path ("foo") / path ("bar")).string () == "foo\\bar");
-#endif
-
- // normalize
- //
-#ifndef _WIN32
- assert (path ("../foo").normalize ().string () == "../foo");
- assert (path ("..///foo").normalize ().string () == "../foo");
- assert (path ("../../foo").normalize ().string () == "../../foo");
- assert (path (".././foo").normalize ().string () == "../foo");
- assert (path (".").normalize ().string () == "");
- assert (path ("./..").normalize ().string () == "..");
- assert (path ("../.").normalize ().string () == "..");
- assert (path ("foo/./..").normalize ().string () == "");
- assert (path ("/foo/./..").normalize ().string () == "/");
- assert (path ("./foo").normalize ().string () == "foo");
-#else
- assert (path ("../foo").normalize ().string () == "..\\foo");
- assert (path ("..///foo").normalize ().string () == "..\\foo");
- assert (path ("..\\../foo").normalize ().string () == "..\\..\\foo");
- assert (path (".././foo").normalize ().string () == "..\\foo");
- assert (path (".").normalize ().string () == "");
- assert (path ("./..").normalize ().string () == "..");
- assert (path ("../.").normalize ().string () == "..");
- assert (path ("foo/./..").normalize ().string () == "");
- assert (path ("C:/foo/./..").normalize ().string () == "C:");
- assert (path ("./foo").normalize ().string () == "foo");
-
- assert (path ("C:").normalize ().string () == "C:");
- assert (path ("C:\\Foo12//Bar").normalize ().string () == "C:\\Foo12\\Bar");
-#endif
-
- // comparison
- //
- assert (path ("./foo") == path("./foo"));
- assert (path ("./boo") < path("./foo"));
-#ifdef _WIN32
- assert (path (".\\foo") == path("./FoO"));
- assert (path (".\\boo") < path(".\\Foo"));
-#endif
-
- // posix_string
- //
- assert (path ("foo/bar/../baz").posix_string () == "foo/bar/../baz");
-#ifdef _WIN32
- assert (path ("foo\\bar\\..\\baz").posix_string () == "foo/bar/../baz");
- try
- {
- path ("c:\\foo\\bar\\..\\baz").posix_string ();
- assert (false);
- }
- catch (const invalid_path&) {}
-#endif
-
- // sub
- //
- assert (path ("foo").sub (path ("foo")));
- assert (path ("foo/bar").sub (path ("foo/bar")));
- assert (path ("foo/bar").sub (path ("foo")));
- assert (!path ("foo/bar").sub (path ("bar")));
- assert (path ("/foo/bar").sub (path ("/foo")));
- assert (path ("/foo/bar/baz").sub (path ("/foo/bar")));
- assert (!path ("/foo/bar/baz").sub (path ("/foo/baz")));
-#ifdef _WIN32
- assert (path ("c:").sub (path ("c:")));
- assert (!path ("c:").sub (path ("d:")));
- assert (path ("c:\\foo").sub (path ("c:")));
-#else
- assert (path ("/foo/bar/baz").sub (path ("/")));
-#endif
-
- // relative
- //
- assert (path ("foo").relative (path ("foo")) == path ());
- assert (path ("foo/bar").relative (path ("foo/bar")) == path ());
- assert (path ("foo/bar/baz").relative (path ("foo/bar")) == path ("baz"));
- assert (path ("foo/bar/baz").relative (path ("foo/bar/buz")).
- posix_string () == "../baz");
- assert (path ("foo/bar/baz").relative (path ("foo/biz/baz")).
- posix_string () == "../../bar/baz");
- assert (path ("foo/bar/baz").relative (path ("fox/bar/baz")).
- posix_string () == "../../../foo/bar/baz");
-#ifdef _WIN32
- assert (path ("c:\\foo\\bar").relative (path ("c:\\fox\\bar")) ==
- path ("..\\..\\foo\\bar"));
- try
- {
- path ("c:\\foo\\bar").relative (path ("d:\\fox\\bar"));
- assert (false);
- }
- catch (const invalid_path&) {}
-#else
- assert (path ("/foo/bar/baz").relative (path ("/")) ==
- path ("foo/bar/baz"));
-#endif
-
- /*
- path p ("../foo");
- p.complete ();
-
- cerr << path::current () << endl;
- cerr << p << endl;
- p.normalize ();
- cerr << p << endl;
- */
-}