From 10f3e17b6dc7718ab00552300871bbfe49854c8b Mon Sep 17 00:00:00 2001 From: Evan Martin Date: Tue, 30 Oct 2012 09:40:59 -0700 Subject: add syntax for checking versions --- configure.py | 3 ++- src/manifest_parser.cc | 12 ++++++++--- src/ninja.cc | 9 +++----- src/version.cc | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/version.h | 32 +++++++++++++++++++++++++++++ 5 files changed, 102 insertions(+), 10 deletions(-) create mode 100644 src/version.cc create mode 100644 src/version.h diff --git a/configure.py b/configure.py index f530ebf..dc6bfb9 100755 --- a/configure.py +++ b/configure.py @@ -279,7 +279,8 @@ for name in ['build', 'manifest_parser', 'metrics', 'state', - 'util']: + 'util', + 'version']: objs += cxx(name) if platform in ('mingw', 'windows'): for name in ['subprocess-win32', diff --git a/src/manifest_parser.cc b/src/manifest_parser.cc index 9d17932..14fca73 100644 --- a/src/manifest_parser.cc +++ b/src/manifest_parser.cc @@ -23,6 +23,7 @@ #include "metrics.h" #include "state.h" #include "util.h" +#include "version.h" ManifestParser::ManifestParser(State* state, FileReader* file_reader) : state_(state), file_reader_(file_reader) { @@ -66,10 +67,15 @@ bool ManifestParser::Parse(const string& filename, const string& input, case Lexer::IDENT: { lexer_.UnreadToken(); string name; - EvalString value; - if (!ParseLet(&name, &value, err)) + EvalString let_value; + if (!ParseLet(&name, &let_value, err)) return false; - env_->AddBinding(name, value.Evaluate(env_)); + string value = let_value.Evaluate(env_); + // Check ninja_required_version immediately so we can exit + // before encountering any syntactic surprises. + if (name == "ninja_required_version") + CheckNinjaVersion(value); + env_->AddBinding(name, value); break; } case Lexer::INCLUDE: diff --git a/src/ninja.cc b/src/ninja.cc index 324b884..06dee8a 100644 --- a/src/ninja.cc +++ b/src/ninja.cc @@ -41,16 +41,13 @@ #include "metrics.h" #include "state.h" #include "util.h" +#include "version.h" // Defined in msvc_helper_main-win32.cc. int MSVCHelperMain(int argc, char** argv); namespace { -/// The version number of the current Ninja release. This will always -/// be "git" on trunk. -const char* kVersion = "git"; - /// Global information passed into subtools. struct Globals { Globals() : state(new State()) {} @@ -121,7 +118,7 @@ void Usage(const BuildConfig& config) { " -d MODE enable debugging (use -d list to list modes)\n" " -t TOOL run a subtool (use -t list to list subtools)\n" " terminates toplevel options; further flags are passed to the tool\n", - kVersion, config.parallelism); + kNinjaVersion, config.parallelism); } /// Choose a default value for the -j (parallelism) flag. @@ -772,7 +769,7 @@ int NinjaMain(int argc, char** argv) { working_dir = optarg; break; case OPT_VERSION: - printf("%s\n", kVersion); + printf("%s\n", kNinjaVersion); return 0; case 'h': default: diff --git a/src/version.cc b/src/version.cc new file mode 100644 index 0000000..7e805c1 --- /dev/null +++ b/src/version.cc @@ -0,0 +1,56 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "version.h" + +#include + +#include "util.h" + +const char* kNinjaVersion = "1.1.0.git"; + +void ParseVersion(const string& version, int* major, int* minor) { + size_t end = version.find('.'); + *major = atoi(version.substr(0, end).c_str()); + *minor = 0; + if (end != string::npos) { + size_t start = end + 1; + end = version.find(start, '.'); + *minor = atoi(version.substr(start, end).c_str()); + } +} + +void CheckNinjaVersion(const string& version) { + int bin_major, bin_minor; + ParseVersion(kNinjaVersion, &bin_major, &bin_minor); + int file_major, file_minor; + ParseVersion(version, &file_major, &file_minor); + + if (bin_major > file_major) { + Warning("ninja executable version (%s) greater than build file " + "ninja_required_version (%s); versions may be incompatible.", + kNinjaVersion, version.c_str()); + return; + } + + if ((bin_major == file_major && bin_minor < file_minor) || + bin_major < file_major) { + Fatal("ninja version (%s) incompatible with build file " + "ninja_required_version version (%s).", + kNinjaVersion, version.c_str()); + } +} + + + diff --git a/src/version.h b/src/version.h new file mode 100644 index 0000000..bd6b9ff --- /dev/null +++ b/src/version.h @@ -0,0 +1,32 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef NINJA_VERSION_H_ +#define NINJA_VERSION_H_ + +#include +using namespace std; + +/// The version number of the current Ninja release. This will always +/// be "git" on trunk. +extern const char* kNinjaVersion; + +/// Parse the major/minor components of a version string. +void ParseVersion(const string& version, int* major, int* minor); + +/// Check whether \a version is compatible with the current Ninja version, +/// aborting if not. +void CheckNinjaVersion(const string& required_version); + +#endif // NINJA_VERSION_H_ -- cgit v0.12