Export Ceres compile definitions to targets compiled against Ceres.

- Previously all Ceres compile definitions were private to Ceres, that
  is they were not exported to users via the CMake export mechanism.
- Now that we use compile definitions in public (installed) Ceres
  headers, we need to export the Ceres compile definitions.
- If we did not do this, then the client's code 'see's' a different
  version of the Ceres headers to those which were in fact compiled,
  or in the case of shared_ptr, may not find the required header.

- This patch makes use of the new, in CMake 2.8.11, function:
  target_compile_definitions() to export all of the Ceres compile
  definitions using CMake's export functionality.
- For CMake versions < 2.8.11, we have to use the blunter instrument of
  calling add_definitions() in CeresConfig.cmake (invoked by a call to
  find_package(Ceres)).  This is messy because it ends up adding the
  Ceres compile definitions to any target declared in the user's code
  after the call to find_package(Ceres).  Although this should do no
  harm as all of our defines are prefaced with CERES_, so any
  unintentional name clashes are unlikely.

Change-Id: I5dea80949190eaf4fb08ea4ac568ce28c32dd4e0
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5110d26..d959669 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -647,6 +647,23 @@
     CLANG_VERSION VERSION_LESS 4.2)
 ENDIF (APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
 
+# Get the complete list of any added compile definitions so that we can
+# export them.  Currently we export all Ceres compile definitions to users
+# of Ceres via FindPackage() except CERES_BUILDING_SHARED_LIBRARY (if present)
+# which controls the behaviour of the CERES_EXPORT macro for MSVC, which
+# we substitute for CERES_USING_SHARED_LIBRARY, which is what users of
+# Ceres should call in MSVC.
+GET_DIRECTORY_PROPERTY(CERES_INTERFACE_COMPILE_DEFINITIONS
+  DIRECTORY ${CMAKE_SOURCE_DIR} COMPILE_DEFINITIONS)
+# Substitute CERES_BUILDING_SHARED_LIBRARY with CERES_USING_SHARED_LIBRARY
+# if building Ceres as a shared library.
+IF (BUILD_SHARED_LIBS)
+  LIST(REMOVE_ITEM CERES_INTERFACE_COMPILE_DEFINITIONS
+    CERES_BUILDING_SHARED_LIBRARY)
+  LIST(APPEND CERES_INTERFACE_COMPILE_DEFINITIONS
+    CERES_USING_SHARED_LIBRARY)
+ENDIF()
+
 ADD_SUBDIRECTORY(internal/ceres)
 
 IF (BUILD_DOCUMENTATION)
diff --git a/cmake/CeresConfig.cmake.in b/cmake/CeresConfig.cmake.in
index 02da766..56a2194 100644
--- a/cmake/CeresConfig.cmake.in
+++ b/cmake/CeresConfig.cmake.in
@@ -51,6 +51,15 @@
 #                  was compiled. This will not include any optional dependencies
 #                  that were disabled when Ceres was compiled.
 #
+# CERES_INTERFACE_COMPILE_DEFINITIONS: List of compile definitions which should be
+#                                   used when compiling a target that uses Ceres
+#                                   Note that these variables will NOT have a -D
+#                                   prefix appended.
+# IMPORTANT: The contents of CERES_INTERFACE_COMPILE_DEFINITIONS will be
+#            AUTOMATICALLY added for you, either via the CMake function
+#            target_compile_definitions() in CMake >= 2.8.11, or via a call to
+#            add_definitions() in CMake < 2.8.11.
+#
 # The following variables are also defined for legacy compatibility only.
 # Any new code should not use them as they do not conform to the standard CMake
 # FindPackage naming conventions.
@@ -67,6 +76,7 @@
   SET(CERES_FOUND FALSE)
   UNSET(CERES_INCLUDE_DIRS)
   UNSET(CERES_LIBRARIES)
+  UNSET(CERES_INTERFACE_COMPILE_DEFINITIONS)
 
   # Reset the CMake module path to its state when this script was called.
   SET(CMAKE_MODULE_PATH ${CALLERS_CMAKE_MODULE_PATH})
@@ -190,6 +200,24 @@
 # Set the expected XX_LIBRARIES variable for FindPackage().
 SET(CERES_LIBRARIES ceres)
 
+# If Ceres was compiled with CMake < 2.8.11, we were not able to use the
+# new (in 2.8.11) target_compile_definitions() function to append the
+# required compile definitions to use when compiling a target that uses
+# Ceres to the Ceres library target.  As such, we need to use add_definitions()
+# to ensure that they will be present.  This is a blunt instrument, as it
+# will add the Ceres definitions to _all_ targets declared from this point
+# on in the caller's project.  Hoever, without requiring the user to
+# explicitly set the flags themselves, this is the only way in CMake
+# versions < 2.8.11.
+SET (CERES_COMPILED_CMAKE_VERSION @CMAKE_VERSION@)
+SET (CERES_INTERFACE_COMPILE_DEFINITIONS @CERES_INTERFACE_COMPILE_DEFINITIONS@)
+IF (CERES_COMPILED_CMAKE_VERSION VERSION_LESS 2.8.11)
+  # The definitions will have been stripped of -D, add it back.
+  FOREACH(DEF ${CERES_INTERFACE_COMPILE_DEFINITIONS})
+    ADD_DEFINITIONS("-D${DEF}")
+  ENDFOREACH()
+ENDIF()
+
 # Set legacy include directories variable for backwards compatibility.
 SET(CERES_INCLUDES ${CERES_INCLUDE_DIRS})
 
diff --git a/internal/ceres/CMakeLists.txt b/internal/ceres/CMakeLists.txt
index b959768..7b7f21d 100644
--- a/internal/ceres/CMakeLists.txt
+++ b/internal/ceres/CMakeLists.txt
@@ -177,6 +177,22 @@
   VERSION ${CERES_VERSION}
   SOVERSION ${CERES_VERSION_MAJOR}
 )
+
+# If we are using CMake >= 2.8.11, make use of the target_compile_definitions()
+# function to append the compile definitions to the exported ceres target, thus
+# any library that finds Ceres via CMake, then adds Ceres to one of its own
+# targets will be compiled with the Ceres compile definitions defined.  This
+# is important for any defines that appear in the installed Ceres header files
+# e.g those related to shared_ptr.
+#
+# If we are using CMake < 2.8.11, then we will have added an add_definitions()
+# call in the CeresConfig.cmake file, which whilst achieving a similar effect,
+# is more of a blunt instrument, as the Ceres definitions will also be added
+# to targets in the users project that do not use Ceres.
+IF (CMAKE_VERSION VERSION_EQUAL 2.8.11 OR
+    CMAKE_VERSION VERSION_GREATER 2.8.11)
+  TARGET_COMPILE_DEFINITIONS(ceres INTERFACE ${CERES_INTERFACE_COMPILE_DEFINITIONS})
+ENDIF()
 TARGET_LINK_LIBRARIES(ceres ${CERES_LIBRARY_DEPENDENCIES})
 
 INSTALL(TARGETS ceres