CMake: option to use cxx_std_11 (minimum) that propagates. (#986)

See https://github.com/abseil/abseil-cpp/issues/259 for context.

This change introduces the ABSL_PROPAGATE_CXX_STD option (default to OFF for now, though it prints a warning in CMake 2.8+ builds that a future Abseil release will default to ON). When enabled, all Abseil CMake targets will set the cxx_std_11 target meta feature (which will then propagate to targets that depend upon Abseil) rather than setting the target-level CXX_STANDARD property to CMAKE_CXX_STANDARD (which is the default value anyway), which doesn't propagate.

Updates README documentation to clarify behavior and with a different example recommendation for library projects (which should generally leave CMAKE_CXX_STANDARD to the root application project).

See https://crascit.com/2015/03/28/enabling-cxx11-in-cmake/ for a useful overview of these different CMake features surrounding C++ standard version configuration.
diff --git a/CMake/AbseilHelpers.cmake b/CMake/AbseilHelpers.cmake
index 6a64a2c..17c4f44 100644
--- a/CMake/AbseilHelpers.cmake
+++ b/CMake/AbseilHelpers.cmake
@@ -254,9 +254,23 @@
       set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/internal)
     endif()
 
-    # INTERFACE libraries can't have the CXX_STANDARD property set
-    set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
-    set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
+    if(ABSL_PROPAGATE_CXX_STD)
+      # Abseil libraries require C++11 as the current minimum standard.
+      # Top-level application CMake projects should ensure a consistent C++
+      # standard for all compiled sources by setting CMAKE_CXX_STANDARD.
+      target_compile_features(${_NAME} PUBLIC cxx_std_11)
+    else()
+      # Note: This is legacy (before CMake 3.8) behavior. Setting the
+      # target-level CXX_STANDARD property to ABSL_CXX_STANDARD (which is
+      # initialized by CMAKE_CXX_STANDARD) should have no real effect, since
+      # that is the default value anyway.
+      #
+      # CXX_STANDARD_REQUIRED does guard against the top-level CMake project
+      # not having enabled CMAKE_CXX_STANDARD_REQUIRED (which prevents
+      # "decaying" to an older standard if the requested one isn't available).
+      set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
+      set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
+    endif()
 
     # When being installed, we lose the absl_ prefix.  We want to put it back
     # to have properly named lib files.  This is a no-op when we are not being
@@ -287,6 +301,16 @@
         ${ABSL_DEFAULT_LINKOPTS}
     )
     target_compile_definitions(${_NAME} INTERFACE ${ABSL_CC_LIB_DEFINES})
+
+    if(ABSL_PROPAGATE_CXX_STD)
+      # Abseil libraries require C++11 as the current minimum standard.
+      # Top-level application CMake projects should ensure a consistent C++
+      # standard for all compiled sources by setting CMAKE_CXX_STANDARD.
+      target_compile_features(${_NAME} INTERFACE cxx_std_11)
+
+      # (INTERFACE libraries can't have the CXX_STANDARD property set, so there
+      # is no legacy behavior else case).
+    endif()
   endif()
 
   # TODO currently we don't install googletest alongside abseil sources, so
@@ -390,8 +414,23 @@
   # Add all Abseil targets to a folder in the IDE for organization.
   set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/test)
 
-  set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
-  set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
+  if(ABSL_PROPAGATE_CXX_STD)
+    # Abseil libraries require C++11 as the current minimum standard.
+    # Top-level application CMake projects should ensure a consistent C++
+    # standard for all compiled sources by setting CMAKE_CXX_STANDARD.
+    target_compile_features(${_NAME} PUBLIC cxx_std_11)
+  else()
+    # Note: This is legacy (before CMake 3.8) behavior. Setting the
+    # target-level CXX_STANDARD property to ABSL_CXX_STANDARD (which is
+    # initialized by CMAKE_CXX_STANDARD) should have no real effect, since
+    # that is the default value anyway.
+    #
+    # CXX_STANDARD_REQUIRED does guard against the top-level CMake project
+    # not having enabled CMAKE_CXX_STANDARD_REQUIRED (which prevents
+    # "decaying" to an older standard if the requested one isn't available).
+    set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
+    set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
+  endif()
 
   add_test(NAME ${_NAME} COMMAND ${_NAME})
 endfunction()
diff --git a/CMake/README.md b/CMake/README.md
index fa8e8d3..f8b27e6 100644
--- a/CMake/README.md
+++ b/CMake/README.md
@@ -34,15 +34,16 @@
 4. Add the **absl::** target you wish to use to the
 [`target_link_libraries()`](https://cmake.org/cmake/help/latest/command/target_link_libraries.html)
 section of your executable or of your library.<br>
-Here is a short CMakeLists.txt example of a project file using Abseil.
+Here is a short CMakeLists.txt example of an application project using Abseil.
 
 ```cmake
-cmake_minimum_required(VERSION 3.5)
-project(my_project)
+cmake_minimum_required(VERSION 3.8.2)
+project(my_app_project)
 
 # Pick the C++ standard to compile with.
 # Abseil currently supports C++11, C++14, and C++17.
 set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
 
 add_subdirectory(abseil-cpp)
 
@@ -50,6 +51,44 @@
 target_link_libraries(my_exe absl::base absl::synchronization absl::strings)
 ```
 
+Note that if you are developing a library designed for use by other clients, you
+should instead leave `CMAKE_CXX_STANDARD` unset (or only set if being built as
+the current top-level CMake project) and configure the minimum required C++
+standard at the target level. If you require a later minimum C++ standard than
+Abseil does, it's a good idea to also enforce that `CMAKE_CXX_STANDARD` (which
+will control Abseil library targets) is set to at least that minimum. For
+example:
+
+```cmake
+cmake_minimum_required(VERSION 3.8.2)
+project(my_lib_project)
+
+# Leave C++ standard up to the root application, so set it only if this is the
+# current top-level CMake project.
+if(CMAKE_SOURCE_DIR STREQUAL my_lib_project_SOURCE_DIR)
+  set(CMAKE_CXX_STANDARD 17)
+  set(CMAKE_CXX_STANDARD_REQUIRED ON)
+endif()
+
+add_subdirectory(abseil-cpp)
+
+add_library(my_lib source.cpp)
+target_link_libraries(my_lib absl::base absl::synchronization absl::strings)
+
+# Enforce that my_lib requires C++17. Important to document for clients that they
+# must set CMAKE_CXX_STANDARD to 17 or higher for proper Abseil ABI compatibility
+# (since otherwise, Abseil library targets could be compiled with a lower C++
+# standard than my_lib).
+target_compile_features(my_lib PUBLIC cxx_std_17)
+if(CMAKE_CXX_STANDARD LESS 17)
+  message(FATAL_ERROR
+      "my_lib_project requires CMAKE_CXX_STANDARD >= 17 (got: ${CMAKE_CXX_STANDARD})")
+endif()
+```
+
+Then the top-level application project that uses your library is responsible for
+setting a consistent `CMAKE_CXX_STANDARD` that is sufficiently high.
+
 ### Running Abseil Tests with CMake
 
 Use the `-DBUILD_TESTING=ON` flag to run Abseil tests.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 42bcbe1..7c8bfff 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -67,6 +67,13 @@
   option(ABSL_ENABLE_INSTALL "Enable install rule" ON)
 endif()
 
+option(ABSL_PROPAGATE_CXX_STD
+  "Use CMake C++ standard meta features (e.g. cxx_std_11) that propagate to targets that link to Abseil"
+  OFF)  # TODO: Default to ON for CMake 3.8 and greater.
+if((${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.8) AND (NOT ABSL_PROPAGATE_CXX_STD))
+  message(WARNING "A future Abseil release will default ABSL_PROPAGATE_CXX_STD to ON for CMake 3.8 and up. We recommend enabling this option to ensure your project still builds correctly.")
+endif()
+
 list(APPEND CMAKE_MODULE_PATH
   ${CMAKE_CURRENT_LIST_DIR}/CMake
   ${CMAKE_CURRENT_LIST_DIR}/absl/copts
diff --git a/FAQ.md b/FAQ.md
index 78028fc..fbd92ce 100644
--- a/FAQ.md
+++ b/FAQ.md
@@ -27,7 +27,10 @@
   file](https://docs.bazel.build/versions/master/guide.html#bazelrc)
 
 If you are using CMake as the build system, you'll need to add a line like
-`set(CMAKE_CXX_STANDARD 17)` to your top level `CMakeLists.txt` file. See the
+`set(CMAKE_CXX_STANDARD 17)` to your top level `CMakeLists.txt` file. If you
+are developing a library designed to be used by other clients, you should
+instead leave `CMAKE_CXX_STANDARD` unset and configure the minimum C++ standard
+required by each of your library targets via `target_compile_features`. See the
 [CMake build
 instructions](https://github.com/abseil/abseil-cpp/blob/master/CMake/README.md)
 for more information.