Make CMake read Ceres version directly from include/ceres/version.h.

- Previously we had the Ceres version defined in two places, one in
  include/ceres/version.h, and one in the main CMakeLists.
- Now the main CMakeLists reads the Ceres version directly from
  version.h, as does the make_release script, so that we have a single
  place (version.h) in which the current Ceres version is defined.

Change-Id: Ie80aa7d38f5b576d3ed4d6109dd699f565c91027
diff --git a/CMakeLists.txt b/CMakeLists.txt
index fc366c9..9b7e841 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -74,15 +74,10 @@
 set(CMAKE_RELEASE_POSTFIX "")
 set(CMAKE_DEBUG_POSTFIX "-debug")
 
-# Important: Always bump the second number (e.g. 1.3.x to 1.4.0) for any
-# release that changes the ABI. The ABI changes for almost any modification to
-# include/ceres (e.g. the public API). If you are unsure about whether
-# something is an ABI change, please ask on the list.
-set(CERES_VERSION_MAJOR 1)
-set(CERES_VERSION_MINOR 11)
-set(CERES_VERSION_PATCH 0)
-set(CERES_VERSION
-    ${CERES_VERSION_MAJOR}.${CERES_VERSION_MINOR}.${CERES_VERSION_PATCH})
+# Read the Ceres version from the source, such that we only ever have a single
+# definition of the Ceres version.
+include(ReadCeresVersionFromSource)
+read_ceres_version_from_source(${CMAKE_SOURCE_DIR})
 
 enable_testing()
 
diff --git a/cmake/ReadCeresVersionFromSource.cmake b/cmake/ReadCeresVersionFromSource.cmake
new file mode 100644
index 0000000..2859744
--- /dev/null
+++ b/cmake/ReadCeresVersionFromSource.cmake
@@ -0,0 +1,81 @@
+# Ceres Solver - A fast non-linear least squares minimizer
+# Copyright 2015 Google Inc. All rights reserved.
+# http://ceres-solver.org/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+#   this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+#   this list of conditions and the following disclaimer in the documentation
+#   and/or other materials provided with the distribution.
+# * Neither the name of Google Inc. nor the names of its contributors may be
+#   used to endorse or promote products derived from this software without
+#   specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# Author: alexs.mac@gmail.com (Alex Stewart)
+#
+
+# Extract Ceres version from <CERES_SOURCE_ROOT>/include/ceres/version.h
+# so that we only have a single definition of the Ceres version, not two
+# one in the source and one in the CMakeLists.txt.
+macro(read_ceres_version_from_source CERES_SOURCE_ROOT)
+  set(CERES_VERSION_FILE ${CERES_SOURCE_ROOT}/include/ceres/version.h)
+  if (NOT EXISTS ${CERES_VERSION_FILE})
+    message(FATAL_ERROR "Cannot find Ceres version.h file in specified "
+      "Ceres source directory: ${CERES_SOURCE_ROOT}, it is not here: "
+      "${CERES_VERSION_FILE}")
+  endif()
+
+  file(READ ${CERES_VERSION_FILE} CERES_VERSION_FILE_CONTENTS)
+
+  string(REGEX MATCH "#define CERES_VERSION_MAJOR [0-9]+"
+    CERES_VERSION_MAJOR "${CERES_VERSION_FILE_CONTENTS}")
+  string(REGEX REPLACE "#define CERES_VERSION_MAJOR ([0-9]+)" "\\1"
+    CERES_VERSION_MAJOR "${CERES_VERSION_MAJOR}")
+  # NOTE: if (VAR) is FALSE if VAR is numeric and <= 0, as such we cannot use
+  #       it for testing version numbers, which might well be zero, at least
+  #       for the patch version, hence check for empty string explicitly.
+  if ("${CERES_VERSION_MAJOR}" STREQUAL "")
+    message(FATAL_ERROR "Failed to extract Ceres major version from "
+      "${CERES_VERSION_FILE}")
+  endif()
+
+  string(REGEX MATCH "#define CERES_VERSION_MINOR [0-9]+"
+    CERES_VERSION_MINOR "${CERES_VERSION_FILE_CONTENTS}")
+  string(REGEX REPLACE "#define CERES_VERSION_MINOR ([0-9]+)" "\\1"
+    CERES_VERSION_MINOR "${CERES_VERSION_MINOR}")
+  if ("${CERES_VERSION_MINOR}" STREQUAL "")
+    message(FATAL_ERROR "Failed to extract Ceres minor version from "
+      "${CERES_VERSION_FILE}")
+  endif()
+
+  string(REGEX MATCH "#define CERES_VERSION_REVISION [0-9]+"
+    CERES_VERSION_PATCH "${CERES_VERSION_FILE_CONTENTS}")
+  string(REGEX REPLACE "#define CERES_VERSION_REVISION ([0-9]+)" "\\1"
+    CERES_VERSION_PATCH "${CERES_VERSION_PATCH}")
+  if ("${CERES_VERSION_PATCH}" STREQUAL "")
+    message(FATAL_ERROR "Failed to extract Ceres patch version from "
+      "${CERES_VERSION_FILE}")
+  endif()
+
+  # This is on a single line s/t CMake does not interpret it as a list of
+  # elements and insert ';' separators which would result in 3.;2.;0 nonsense.
+  set(CERES_VERSION "${CERES_VERSION_MAJOR}.${CERES_VERSION_MINOR}.${CERES_VERSION_PATCH}")
+
+  message(STATUS "Detected Ceres version: ${CERES_VERSION} from "
+    "${CERES_VERSION_FILE}")
+endmacro()
diff --git a/scripts/make_release b/scripts/make_release
index f146fe1..ce5d5cd 100755
--- a/scripts/make_release
+++ b/scripts/make_release
@@ -40,14 +40,16 @@
 
 TMP="/tmp/ceres-solver-$1"
 DOCS_TMP="/tmp/ceres-solver-docs-$1"
-VERSION=$(grep 'set(CERES_VERSION_' CMakeLists.txt | \
-          sed -e 's/\(.*\) \(.*\))/\2/' | \
-          tr '\n' '.' | sed -e 's/.$//')
+VERSION=$(grep '#define CERES_VERSION_' include/ceres/version.h | \
+          sed -e 's/#define CERES_VERSION_STRING.*$//' | \
+          sed -e 's/\(^#define CERES_VERSION_[MR^S].[A-Z]*\) \([0-9]\)/\2/' | \
+          tr '\n' '.' | \
+          sed -e 's/..$//')
 GIT_COMMIT=$(git log -1 HEAD |grep commit)
 
 if [[ $1 != $VERSION ]] ; then
   echo "ERROR: Version from the command line $1 does not match CERES_VERSION"
-  echo "       in CMakeLists.txt, which is $VERSION. You may not be in the "
+  echo "       in include/ceres/version.h, which is $VERSION. You may not be in the "
   echo "       toplevel source dir."
   exit 1
 fi