From 593fd960891027b97567b2622ed4b6c16070ab36 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 28 Apr 2017 08:33:42 +0200 Subject: Implement support for pre-processing version headers (or other files) Also implement the build system version check. --- build2/version/init.cxx | 78 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 4 deletions(-) (limited to 'build2/version/init.cxx') diff --git a/build2/version/init.cxx b/build2/version/init.cxx index 947f4a8..d111af5 100644 --- a/build2/version/init.cxx +++ b/build2/version/init.cxx @@ -28,6 +28,7 @@ namespace build2 static const path manifest ("manifest"); static const version_doc version_doc_; + static const version_in version_in_; void boot (scope& rs, const location& l, unique_ptr& mod) @@ -38,6 +39,7 @@ namespace build2 // Extract the version from the manifest file. // standard_version v; + dependency_constraints ds; { path f (rs.src_path () / manifest); @@ -65,7 +67,73 @@ namespace build2 { fail << "invalid standard version '" << nv.value << "': " << e; } - break; + } + else if (nv.name == "depends") + { + // According to the package manifest spec, the format of the + // 'depends' value is as follows: + // + // depends: [?][*] [; ] + // + // := [ '|' ]* + // := [] + // := | + // := ('==' | '>' | '<' | '>=' | '<=') + // := ('(' | '[') (')' | ']') + // + // Note that we don't do exhaustive validation here leaving it + // to the package manager. + // + string v (move (nv.value)); + + size_t p; + + // Get rid of the comment. + // + if ((p = v.find (';')) != string::npos) + v.resize (p); + + // Get rid of conditional/runtime markers. Note that enither of + // them is valid in the rest of the value. + // + if ((p = v.find_last_of ("?*")) != string::npos) + v.erase (0, p + 1); + + // Parse as |-separated "words". + // + for (size_t b (0), e (0); next_word (v, b, e, '|'); ) + { + string d (v, b, e - b); + trim (d); + + p = d.find_first_of (" \t=<>[("); + string n (d, 0, p); + string c (p != string::npos ? string (d, p) : string ()); + + trim (n); + trim (c); + + // If this is a dependency on the build system itself, check + // it (so there is no need for explicit using build@X.Y.Z). + // + if (n == "build2" && !c.empty ()) + try + { + standard_version_constraint vc (c); + + if (!vc.satisfies (build_version)) + fail (l) << "incompatible build2 version" << + info << "running " << build_version.string () << + info << "required " << vc.string (); + } + catch (const invalid_argument& e) + { + fail (l) << "invalid version constraint for dependency " + << b << ": " << e; + } + + ds.emplace (move (n), move (c)); + } } } } @@ -91,7 +159,6 @@ namespace build2 // snapshot sn and id (e.g., commit date and id from git). If there is // uncommitted stuff, then leave it as .z. // - bool patched (false); if (v.snapshot () && v.snapshot_sn == standard_version::latest_sn) { snapshot ss (extract_snapshot (rs)); @@ -100,7 +167,6 @@ namespace build2 { v.snapshot_sn = ss.sn; v.snapshot_id = move (ss.id); - patched = true; } } @@ -155,7 +221,7 @@ namespace build2 // Create the module. // - mod.reset (new module (move (v), patched)); + mod.reset (new module (move (v), move (ds))); } static void @@ -211,6 +277,10 @@ namespace build2 r.insert (perform_update_id, "version.doc", version_doc_); r.insert (perform_clean_id, "version.doc", version_doc_); r.insert (configure_update_id, "version.doc", version_doc_); + + r.insert (perform_update_id, "version.in", version_in_); + r.insert (perform_clean_id, "version.in", version_in_); + r.insert (configure_update_id, "version.in", version_in_); } return true; -- cgit v1.1