aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/bin
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2019-10-08 09:33:45 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2019-10-08 09:33:45 +0200
commitd730f40440e213bc08cce4587439960c80ad9aa5 (patch)
treeec0d488f7dd83238accaab33db8660ae32b60870 /libbuild2/bin
parent2c8b400010ffedec596969f64e79144f99d73f62 (diff)
Redo bin pattern as PATH-like search paths rather than fallback directory
Also, unlike the fallback directory, the search paths are searched first rather than last.
Diffstat (limited to 'libbuild2/bin')
-rw-r--r--libbuild2/bin/guess.cxx105
-rw-r--r--libbuild2/bin/guess.hxx6
-rw-r--r--libbuild2/bin/init.cxx62
3 files changed, 94 insertions, 79 deletions
diff --git a/libbuild2/bin/guess.cxx b/libbuild2/bin/guess.cxx
index 68ef827..633c798 100644
--- a/libbuild2/bin/guess.cxx
+++ b/libbuild2/bin/guess.cxx
@@ -37,37 +37,60 @@ namespace build2
return v ? *v : semantic_version ();
}
- ar_info
- guess_ar (const path& ar, const path* rl, const dir_path& fallback)
+ // Search for a program first in paths if not NULL and then using the
+ // standard path search semantics. Use var to suggest an override if the
+ // search fails.
+ //
+ // Only search in PATH (specifically, omitting the current executable's
+ // directory on Windows).
+ //
+ static process_path
+ search (const path& prog, const char* paths, const char* var)
{
- tracer trace ("bin::guess_ar");
-
- process_path arp, rlp;
- guess_result arr, rlr;
-
+ if (paths != nullptr)
{
- auto df = make_diag_frame (
- [](const diag_record& dr)
- {
- dr << info << "use config.bin.ar to override";
- });
+ process_path r (
+ try_run_search (prog,
+ true /* init */,
+ dir_path () /* fallback */,
+ true /* path_only */,
+ paths));
- // Only search in PATH (specifically, omitting the current
- // executable's directory on Windows).
- //
- arp = run_search (ar, true, fallback, true /* path_only */);
+ if (!r.empty ())
+ {
+ // Clear the recall path since we found it in custom search paths.
+ // An alternative would have been to also do a search in PATH and if
+ // the two effective paths are the same (which means, this program
+ // is also in PATH), keep the recall. The benefit of this approach
+ // is that we will have tidier command lines without long absolute
+ // paths. The drawback is the extra complexity (we would need to
+ // normalize the paths, etc). Let's keep it simple for now.
+ //
+ r.clear_recall ();
+ return r;
+ }
}
- if (rl != nullptr)
- {
- auto df = make_diag_frame (
- [](const diag_record& dr)
- {
- dr << info << "use config.bin.ranlib to override";
- });
+ auto df = make_diag_frame (
+ [var](const diag_record& dr)
+ {
+ dr << info << "use " << var << " to override";
+ });
- rlp = run_search (*rl, true, fallback, true /* path_only */);
- }
+ return run_search (prog, true, dir_path (), true);
+ }
+
+ ar_info
+ guess_ar (const path& ar, const path* rl, const char* paths)
+ {
+ tracer trace ("bin::guess_ar");
+
+ guess_result arr, rlr;
+
+ process_path arp (search (ar, paths, "config.bin.ar"));
+ process_path rlp (rl != nullptr
+ ? search (*rl, paths, "config.bin.ranlib")
+ : process_path ());
// Binutils, LLVM, and FreeBSD ar/ranlib all recognize the --version
// option. While Microsoft's lib.exe doesn't support --version, it only
@@ -258,25 +281,13 @@ namespace build2
}
ld_info
- guess_ld (const path& ld, const dir_path& fallback)
+ guess_ld (const path& ld, const char* paths)
{
tracer trace ("bin::guess_ld");
guess_result r;
- process_path pp;
- {
- auto df = make_diag_frame (
- [](const diag_record& dr)
- {
- dr << info << "use config.bin.ld to override";
- });
-
- // Only search in PATH (specifically, omitting the current
- // executable's directory on Windows).
- //
- pp = run_search (ld, true, fallback, true /* path_only */);
- }
+ process_path pp (search (ld, paths, "config.bin.ld"));
// Binutils ld recognizes the --version option. Microsoft's link.exe
// doesn't support --version (nor any other way to get the version
@@ -389,25 +400,13 @@ namespace build2
}
rc_info
- guess_rc (const path& rc, const dir_path& fallback)
+ guess_rc (const path& rc, const char* paths)
{
tracer trace ("bin::guess_rc");
guess_result r;
- process_path pp;
- {
- auto df = make_diag_frame (
- [](const diag_record& dr)
- {
- dr << info << "use config.bin.rc to override";
- });
-
- // Only search in PATH (specifically, omitting the current
- // executable's directory on Windows).
- //
- pp = run_search (rc, true, fallback, true /* path_only */);
- }
+ process_path pp (search (rc, paths, "config.bin.rc"));
// Binutils windres recognizes the --version option.
//
diff --git a/libbuild2/bin/guess.hxx b/libbuild2/bin/guess.hxx
index 0e04ba5..b4239c2 100644
--- a/libbuild2/bin/guess.hxx
+++ b/libbuild2/bin/guess.hxx
@@ -46,7 +46,7 @@ namespace build2
// attemplated and the returned ranlib_* members will be left empty.
//
ar_info
- guess_ar (const path& ar, const path* ranlib, const dir_path& fallback);
+ guess_ar (const path& ar, const path* ranlib, const char* paths);
// ld information.
//
@@ -77,7 +77,7 @@ namespace build2
};
ld_info
- guess_ld (const path& ld, const dir_path& fallback);
+ guess_ld (const path& ld, const char* paths);
// rc information.
//
@@ -101,7 +101,7 @@ namespace build2
};
rc_info
- guess_rc (const path& rc, const dir_path& fallback);
+ guess_rc (const path& rc, const char* paths);
}
}
diff --git a/libbuild2/bin/init.cxx b/libbuild2/bin/init.cxx
index d56e0a5..7f7fd02 100644
--- a/libbuild2/bin/init.cxx
+++ b/libbuild2/bin/init.cxx
@@ -37,6 +37,30 @@ namespace build2
static const strings liba_lib {"static", "shared"};
static const strings libs_lib {"shared", "static"};
+ struct pattern_paths
+ {
+ const char* pattern = nullptr;
+ const char* paths = nullptr;
+ };
+
+ static inline pattern_paths
+ lookup_pattern (scope& rs)
+ {
+ pattern_paths r;
+
+ // Theoretically, we could have both the pattern and the search paths,
+ // for example, the pattern can come first followed by the paths.
+ //
+ if (const string* v = cast_null<string> (rs["bin.pattern"]))
+ {
+ (path::traits_type::is_separator (v->back ())
+ ? r.paths
+ : r.pattern) = v->c_str ();
+ }
+
+ return r;
+ }
+
bool
vars_init (scope& rs,
scope&,
@@ -370,7 +394,9 @@ namespace build2
(!path::traits_type::is_separator (s.back ()) &&
s.find ('*') == string::npos))
{
- fail << "missing '*' in binutils pattern '" << s << "'";
+ fail << "missing '*' or trailing '"
+ << path::traits_type::directory_separator
+ << "' in binutils pattern '" << s << "'";
}
rs.assign<string> ("bin.pattern") = s;
@@ -602,12 +628,9 @@ namespace build2
const string& tsys (cast<string> (rs["bin.target.system"]));
const char* ar_d (tsys == "win32-msvc" ? "lib" : "ar");
- // This can be either a pattern or a fallback search directory.
+ // This can be either a pattern or search path(s).
//
- const string* pat (cast_null<string> (rs["bin.pattern"]));
-
- bool fb (pat != nullptr &&
- path::traits_type::is_separator (pat->back ()));
+ pattern_paths pat (lookup_pattern (rs));
// Don't save the default value to config.build so that if the user
// changes, say, the C++ compiler (which hinted the pattern), then
@@ -617,7 +640,7 @@ namespace build2
config::required (
rs,
"config.bin.ar",
- path (apply_pattern (ar_d, fb ? nullptr : pat)),
+ path (apply_pattern (ar_d, pat.pattern)),
false,
config::save_commented));
@@ -632,8 +655,7 @@ namespace build2
const path& ar (cast<path> (ap.first));
const path* ranlib (cast_null<path> (rp.first));
- ar_info ari (
- guess_ar (ar, ranlib, fb ? dir_path (*pat) : dir_path ()));
+ ar_info ari (guess_ar (ar, ranlib, pat.paths));
// If this is a new value (e.g., we are configuring), then print the
// report at verbosity level 2 and up (-v).
@@ -762,23 +784,20 @@ namespace build2
const string& tsys (cast<string> (rs["bin.target.system"]));
const char* ld_d (tsys == "win32-msvc" ? "link" : "ld");
- // This can be either a pattern or a fallback search directory.
+ // This can be either a pattern or search path(s).
//
- const string* pat (cast_null<string> (rs["bin.pattern"]));
-
- bool fb (pat != nullptr &&
- path::traits_type::is_separator (pat->back ()));
+ pattern_paths pat (lookup_pattern (rs));
auto p (
config::required (
rs,
"config.bin.ld",
- path (apply_pattern (ld_d, fb ? nullptr : pat)),
+ path (apply_pattern (ld_d, pat.pattern)),
false,
config::save_commented));
const path& ld (cast<path> (p.first));
- ld_info ldi (guess_ld (ld, fb ? dir_path (*pat) : dir_path ()));
+ ld_info ldi (guess_ld (ld, pat.paths));
// If this is a new value (e.g., we are configuring), then print the
// report at verbosity level 2 and up (-v).
@@ -875,23 +894,20 @@ namespace build2
const string& tsys (cast<string> (rs["bin.target.system"]));
const char* rc_d (tsys == "win32-msvc" ? "rc" : "windres");
- // This can be either a pattern or a fallback search directory.
+ // This can be either a pattern or search path(s).
//
- const string* pat (cast_null<string> (rs["bin.pattern"]));
-
- bool fb (pat != nullptr &&
- path::traits_type::is_separator (pat->back ()));
+ pattern_paths pat (lookup_pattern (rs));
auto p (
config::required (
rs,
"config.bin.rc",
- path (apply_pattern (rc_d, fb ? nullptr : pat)),
+ path (apply_pattern (rc_d, pat.pattern)),
false,
config::save_commented));
const path& rc (cast<path> (p.first));
- rc_info rci (guess_rc (rc, fb ? dir_path (*pat) : dir_path ()));
+ rc_info rci (guess_rc (rc, pat.paths));
// If this is a new value (e.g., we are configuring), then print the
// report at verbosity level 2 and up (-v).