aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/rule.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2020-05-18 09:55:00 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2020-05-27 08:35:29 +0200
commit98db2c71fa8175c1680ab2c6cca07c4c00853047 (patch)
tree3d70149284b03c8f2b4e06521abca1b55f788ae3 /libbuild2/rule.cxx
parent66834a2d66bdcd36013afd7c3325acd9acf4a0b6 (diff)
Add support for recipe location update
Diffstat (limited to 'libbuild2/rule.cxx')
-rw-r--r--libbuild2/rule.cxx119
1 files changed, 77 insertions, 42 deletions
diff --git a/libbuild2/rule.cxx b/libbuild2/rule.cxx
index 32f161b..c3d8f88 100644
--- a/libbuild2/rule.cxx
+++ b/libbuild2/rule.cxx
@@ -686,45 +686,48 @@ namespace build2
string sym ("load_" + id);
- optional<bool> altn (false); // Standard naming scheme.
- if (!is_src_root (pd, altn))
+ // Update the project is necessary.
+ //
+ path of;
+ try
{
const uint16_t verbosity (3);
- // Write ad hoc config.build that loads the ~build2 configuration.
- // This way the configuration will be always in sync with ~build2 and
- // we can update the recipe manually (e.g., for debugging).
- //
- create_project (
- pd,
- dir_path (), /* amalgamation */
- {}, /* boot_modules */
- "cxx.std = latest", /* root_pre */
- {"cxx."}, /* root_modules */
- "", /* root_post */
- string ("config"), /* config_module */
- string ("config.config.load = ~build2"), /* config_file */
- false, /* buildfile */
- "build2 core", /* who */
- verbosity); /* verbosity */
-
- path f;
-
- try
+ ofdstream ofs;
+
+ optional<bool> altn (false); // Standard naming scheme.
+ if (!is_src_root (pd, altn))
{
- ofdstream ofs;
- // Write source file.
+ // Write ad hoc config.build that loads the ~build2 configuration.
+ // This way the configuration will be always in sync with ~build2
+ // and we can update the recipe manually (e.g., for debugging).
//
- f = path (pd / "rule.cxx");
+ create_project (
+ pd,
+ dir_path (), /* amalgamation */
+ {}, /* boot_modules */
+ "cxx.std = latest", /* root_pre */
+ {"cxx."}, /* root_modules */
+ "", /* root_post */
+ string ("config"), /* config_module */
+ string ("config.config.load = ~build2"), /* config_file */
+ false, /* buildfile */
+ "build2 core", /* who */
+ verbosity); /* verbosity */
+
+
+ // Write the rule source file.
+ //
+ of = path (pd / "rule.cxx");
if (verb >= verbosity)
- text << (verb >= 2 ? "cat >" : "save ") << f;
+ text << (verb >= 2 ? "cat >" : "save ") << of;
- ofs.open (f);
+ ofs.open (of);
- ofs << "// " << loc << endl
- << endl;
+ ofs << "#include \"location.hxx\"" << '\n'
+ << '\n';
// Include every header that can plausibly be needed by a rule.
//
@@ -795,14 +798,9 @@ namespace build2
// buildfile. Note that there is no easy way to restore things to
// point back to the source file (other than another #line with a
// line and a file). Seeing that we don't have much after, let's not
- // bother for now. Note that the code start from the next line thus
- // +1.
- //
- // @@ TODO: need to escape backslashes in path.
+ // bother for now.
//
- if (!loc.file.path.empty ())
- ofs << "#line " << loc.line + 1 << " \"" <<
- loc.file.path.string () << '"' << '\n';
+ ofs << "#line RECIPE_LINE RECIPE_FILE" << '\n';
// Note that the code always includes trailing newline.
//
@@ -832,24 +830,61 @@ namespace build2
ofs.close ();
+
// Write buildfile.
//
- f = path (pd / std_buildfile_file);
+ of = path (pd / std_buildfile_file);
if (verb >= verbosity)
- text << (verb >= 2 ? "cat >" : "save ") << f;
+ text << (verb >= 2 ? "cat >" : "save ") << of;
- ofs.open (f);
+ ofs.open (of);
ofs << "import imp_libs += build2%lib{build2}" << '\n'
- << "libs{" << id << "}: cxx{rule} $imp_libs" << '\n';
+ << "libs{" << id << "}: cxx{rule} hxx{location} $imp_libs"<< '\n';
ofs.close ();
}
- catch (const io_error& e)
+
+ // Create/update the recipe location header.
+ //
+ // For update, preserve the file timestamp in order not to render the
+ // recipe out of date.
+ //
+ of = path (pd / "location.hxx");
+
+ entry_time et (file_time (of));
+
+ if (verb >= verbosity)
+ text << (verb >= 2 ? "cat >" : "save ") << of;
+
+ ofs.open (of);
+
+ // Recipe file and line for the #line directive above. Note that the
+ // code starts from the next line thus +1. We also need to escape
+ // backslashes (Windows paths).
+ //
{
- fail << "unable to write to " << f << ": " << e;
+ const string& f (!loc.file.path.empty ()
+ ? loc.file.path.string ()
+ : loc.file.name ? *loc.file.name : string ());
+
+ ofs << "#define RECIPE_FILE \"" << sanitize_strlit (f) << '"' << '\n'
+ << "#define RECIPE_LINE " << loc.line + 1 << '\n';
}
+
+ ofs.close ();
+
+ if (et.modification != timestamp_nonexistent)
+ file_time (of, et);
+ }
+ catch (const io_error& e)
+ {
+ fail << "unable to write to " << of << ": " << e;
+ }
+ catch (const system_error& e)
+ {
+ fail << "unable to get/set timestamp for " << of << ": " << e;
}
// Update the library target in the module context.