aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-07-11 07:23:37 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-07-11 07:23:37 +0200
commit0760742386e8e6034bbd619487ef156bc574e408 (patch)
tree8b4df6a356e5424f89a94464809349bbde667189
parentfac576a331d6587e4343d09d6caf959d9a776118 (diff)
Add bin.rc module (resource compiler)
-rw-r--r--build2/b.cxx1
-rw-r--r--build2/bin/guess31
-rw-r--r--build2/bin/guess.cxx57
-rw-r--r--build2/bin/module9
-rw-r--r--build2/bin/module.cxx105
5 files changed, 179 insertions, 24 deletions
diff --git a/build2/b.cxx b/build2/b.cxx
index f272926..6138f6c 100644
--- a/build2/b.cxx
+++ b/build2/b.cxx
@@ -190,6 +190,7 @@ main (int argc, char* argv[])
builtin_modules["bin"] = module_functions {nullptr, &bin::init};
builtin_modules["bin.ld"] = module_functions {nullptr, &bin::ld_init};
+ builtin_modules["bin.rc"] = module_functions {nullptr, &bin::rc_init};
builtin_modules["cxx"] = module_functions {nullptr, &cxx::init};
builtin_modules["cli"] = module_functions {nullptr, &cli::init};
diff --git a/build2/bin/guess b/build2/bin/guess
index d6ff76d..10f337a 100644
--- a/build2/bin/guess
+++ b/build2/bin/guess
@@ -48,7 +48,7 @@ namespace build2
// ld information.
//
- // Currently recognized ld and their ids:
+ // Currently recognized linkers and their ids:
//
// gnu GNU binutils ld.bfd
// gold GNU binutils ld.gold
@@ -68,13 +68,36 @@ namespace build2
//
struct ld_info
{
- string ld_id;
- string ld_signature;
- string ld_checksum;
+ string id;
+ string signature;
+ string checksum;
};
ld_info
guess_ld (const path& ld);
+
+ // rc information.
+ //
+ // Currently recognized resource compilers and their ids:
+ //
+ // gnu GNU binutils windres
+ // msvc Microsoft's rc.exe
+ //
+ // The signature is normally the --version line.
+ //
+ // The checksum is used to detect rc changes. It is calculated in a
+ // toolchain-specific manner (usually the output of --version) and is not
+ // bulletproof.
+ //
+ struct rc_info
+ {
+ string id;
+ string signature;
+ string checksum;
+ };
+
+ rc_info
+ guess_rc (const path& rc);
}
}
diff --git a/build2/bin/guess.cxx b/build2/bin/guess.cxx
index ea4ac49..8a91015 100644
--- a/build2/bin/guess.cxx
+++ b/build2/bin/guess.cxx
@@ -282,5 +282,62 @@ namespace build2
return ld_info {move (r.id), move (r.signature), move (r.checksum)};
}
+
+ rc_info
+ guess_rc (const path& rc)
+ {
+ tracer trace ("bin::guess_rc");
+
+ guess_result r;
+
+ // Binutils windres recognizes the --version option.
+ //
+ {
+ auto f = [] (string& l) -> guess_result
+ {
+ // Binutils windres --version output has a line that starts with
+ // "GNU windres ".
+ //
+ if (l.compare (0, 12, "GNU windres ") == 0)
+ return guess_result {"gnu", move (l), ""};
+
+ return guess_result ();
+ };
+
+ // Suppress all the errors because we may be trying an unsupported
+ // option.
+ //
+ sha256 cs;
+ r = run<guess_result> (rc, "--version", f, false, false, &cs);
+
+ if (!r.empty ())
+ r.checksum = cs.string ();
+ }
+
+ // Microsoft rc.exe /? prints its standard banner and exits with zero
+ // status.
+ //
+ if (r.empty ())
+ {
+ auto f = [] (string& l) -> guess_result
+ {
+ if (l.compare (0, 14, "Microsoft (R) ") == 0)
+ return guess_result {"msvc", move (l), ""};
+
+ return guess_result ();
+ };
+
+ sha256 cs;
+ r = run<guess_result> (rc, "/?", f, false, false, &cs);
+
+ if (!r.empty ())
+ r.checksum = cs.string ();
+ }
+
+ if (r.empty ())
+ fail << "unable to guess " << rc << " signature";
+
+ return rc_info {move (r.id), move (r.signature), move (r.checksum)};
+ }
}
}
diff --git a/build2/bin/module b/build2/bin/module
index fa592cf..668e4d8 100644
--- a/build2/bin/module
+++ b/build2/bin/module
@@ -31,6 +31,15 @@ namespace build2
bool,
bool,
const variable_map&);
+
+ bool
+ rc_init (scope&,
+ scope&,
+ const location&,
+ unique_ptr<module_base>&,
+ bool,
+ bool,
+ const variable_map&);
}
}
diff --git a/build2/bin/module.cxx b/build2/bin/module.cxx
index f5e44db..306d8de 100644
--- a/build2/bin/module.cxx
+++ b/build2/bin/module.cxx
@@ -305,7 +305,7 @@ namespace build2
const path& ar (cast<path> (p.first));
const path& ranlib (v ? cast<path> (v) : path ());
- ar_info ai (guess_ar (ar, ranlib));
+ ar_info ari (guess_ar (ar, ranlib));
// If this is a new value (e.g., we are configuring), then print the
// report at verbosity level 2 and up (-v).
@@ -316,30 +316,31 @@ namespace build2
text << "bin.ar\n"
<< " exe " << ar << '\n'
- << " id " << ai.ar_id << '\n'
- << " signature " << ai.ar_signature << '\n'
- << " checksum " << ai.ar_checksum;
+ << " id " << ari.ar_id << '\n'
+ << " signature " << ari.ar_signature << '\n'
+ << " checksum " << ari.ar_checksum;
if (!ranlib.empty ())
{
text << "bin.ranlib\n"
<< " exe " << ranlib << '\n'
- << " id " << ai.ranlib_id << '\n'
- << " signature " << ai.ranlib_signature << '\n'
- << " checksum " << ai.ranlib_checksum;
+ << " id " << ari.ranlib_id << '\n'
+ << " signature " << ari.ranlib_signature << '\n'
+ << " checksum " << ari.ranlib_checksum;
}
}
- r.assign<string> ("bin.ar.id") = move (ai.ar_id);
- r.assign<string> ("bin.ar.signature") = move (ai.ar_signature);
- r.assign<string> ("bin.ar.checksum") = move (ai.ar_checksum);
+ r.assign<string> ("bin.ar.id") = move (ari.ar_id);
+ r.assign<string> ("bin.ar.signature") = move (ari.ar_signature);
+ r.assign<string> ("bin.ar.checksum") = move (ari.ar_checksum);
if (!ranlib.empty ())
{
- r.assign<string> ("bin.ranlib.id") = move (ai.ranlib_id);
+ r.assign<string> ("bin.ranlib.id") = move (ari.ranlib_id);
r.assign<string> ("bin.ranlib.signature") =
- move (ai.ranlib_signature);
- r.assign<string> ("bin.ranlib.checksum") = move (ai.ranlib_checksum);
+ move (ari.ranlib_signature);
+ r.assign<string> ("bin.ranlib.checksum") =
+ move (ari.ranlib_checksum);
}
}
@@ -464,7 +465,7 @@ namespace build2
path (apply (r["bin.pattern"], ld_d))));
const path& ld (cast<path> (p.first));
- ld_info li (guess_ld (ld));
+ ld_info ldi (guess_ld (ld));
// If this is a new value (e.g., we are configuring), then print the
// report at verbosity level 2 and up (-v).
@@ -473,14 +474,78 @@ namespace build2
{
text << "bin.ld\n"
<< " exe " << ld << '\n'
- << " id " << li.ld_id << '\n'
- << " signature " << li.ld_signature << '\n'
- << " checksum " << li.ld_checksum;
+ << " id " << ldi.id << '\n'
+ << " signature " << ldi.signature << '\n'
+ << " checksum " << ldi.checksum;
}
- r.assign<string> ("bin.ld.id") = move (li.ld_id);
- r.assign<string> ("bin.ld.signature") = move (li.ld_signature);
- r.assign<string> ("bin.ld.checksum") = move (li.ld_checksum);
+ r.assign<string> ("bin.ld.id") = move (ldi.id);
+ r.assign<string> ("bin.ld.signature") = move (ldi.signature);
+ r.assign<string> ("bin.ld.checksum") = move (ldi.checksum);
+ }
+
+ return true;
+ }
+
+ bool
+ rc_init (scope& r,
+ scope& b,
+ const location& loc,
+ unique_ptr<module_base>&,
+ bool first,
+ bool,
+ const variable_map& config_hints)
+ {
+ tracer trace ("bin::rc_init");
+ l5 ([&]{trace << "for " << b.out_path ();});
+
+ // Make sure the bin core is loaded.
+ //
+ if (!cast_false<bool> (b["bin.loaded"]))
+ load_module ("bin", r, b, loc, false, config_hints);
+
+ // Enter module variables.
+ //
+ if (first)
+ {
+ auto& v (var_pool);
+
+ v.insert<path> ("config.bin.rc", true);
+ }
+
+ // Configure.
+ //
+ if (first)
+ {
+ // config.bin.rc
+ //
+ // Use the target to decide on the default rc name.
+ //
+ const string& tsys (cast<string> (r["bin.target.system"]));
+ const char* rc_d (tsys == "win32-msvc" ? "rc" : "windres");
+
+ auto p (config::required (r,
+ "config.bin.rc",
+ path (apply (r["bin.pattern"], rc_d))));
+
+ const path& rc (cast<path> (p.first));
+ rc_info rci (guess_rc (rc));
+
+ // If this is a new value (e.g., we are configuring), then print the
+ // report at verbosity level 2 and up (-v).
+ //
+ if (verb >= (p.second ? 2 : 3))
+ {
+ text << "bin.rc\n"
+ << " exe " << rc << '\n'
+ << " id " << rci.id << '\n'
+ << " signature " << rci.signature << '\n'
+ << " checksum " << rci.checksum;
+ }
+
+ r.assign<string> ("bin.rc.id") = move (rci.id);
+ r.assign<string> ("bin.rc.signature") = move (rci.signature);
+ r.assign<string> ("bin.rc.checksum") = move (rci.checksum);
}
return true;