CMake project updates

A series of improvements:

- Improved Protobuf module compatibility (disabled by default);
- Hide advanced settings;
- Added build tree configuration;
- Added build of examples.
diff --git a/cmake/protobuf-module.cmake.in b/cmake/protobuf-module.cmake.in
index d81dc45..7ced934 100644
--- a/cmake/protobuf-module.cmake.in
+++ b/cmake/protobuf-module.cmake.in
@@ -1,7 +1,4 @@
-if(PROTOBUF_SRC_ROOT_FOLDER)
-  message(AUTHOR_WARNING "Variable PROTOBUF_SRC_ROOT_FOLDER defined, but not"
-    " used in CONFIG mode")
-endif()
+# Functions
 
 function(PROTOBUF_GENERATE_CPP SRCS HDRS)
   if(NOT ARGN)
@@ -23,12 +20,8 @@
     set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})
   endif()
 
-  # Add well-known type protos include path
-  list(APPEND _protobuf_include_path
-    -I "${_PROTOBUF_IMPORT_PREFIX}/@CMAKE_INSTALL_INCLUDEDIR@")
-
-  if(DEFINED PROTOBUF_IMPORT_DIRS)
-    foreach(DIR ${PROTOBUF_IMPORT_DIRS})
+  if(DEFINED Protobuf_IMPORT_DIRS)
+    foreach(DIR ${Protobuf_IMPORT_DIRS})
       get_filename_component(ABS_PATH ${DIR} ABSOLUTE)
       list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
       if(${_contains_already} EQUAL -1)
@@ -49,11 +42,11 @@
     add_custom_command(
       OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc"
              "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h"
-      COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
+      COMMAND  ${Protobuf_PROTOC_EXECUTABLE}
       ARGS --cpp_out  ${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_include_path} ${ABS_FIL}
-      DEPENDS ${ABS_FIL} ${PROTOBUF_PROTOC_EXECUTABLE}
+      DEPENDS ${ABS_FIL} ${Protobuf_PROTOC_EXECUTABLE}
       COMMENT "Running C++ protocol buffer compiler on ${FIL}"
-      VERBATIM)
+      VERBATIM )
   endforeach()
 
   set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
@@ -61,29 +54,110 @@
   set(${HDRS} ${${HDRS}} PARENT_SCOPE)
 endfunction()
 
+function(PROTOBUF_GENERATE_PYTHON SRCS)
+  if(NOT ARGN)
+    message(SEND_ERROR "Error: PROTOBUF_GENERATE_PYTHON() called without any proto files")
+    return()
+  endif()
+
+  if(PROTOBUF_GENERATE_CPP_APPEND_PATH)
+    # Create an include path for each file specified
+    foreach(FIL ${ARGN})
+      get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
+      get_filename_component(ABS_PATH ${ABS_FIL} PATH)
+      list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
+      if(${_contains_already} EQUAL -1)
+          list(APPEND _protobuf_include_path -I ${ABS_PATH})
+      endif()
+    endforeach()
+  else()
+    set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})
+  endif()
+
+  if(DEFINED Protobuf_IMPORT_DIRS)
+    foreach(DIR ${Protobuf_IMPORT_DIRS})
+      get_filename_component(ABS_PATH ${DIR} ABSOLUTE)
+      list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
+      if(${_contains_already} EQUAL -1)
+          list(APPEND _protobuf_include_path -I ${ABS_PATH})
+      endif()
+    endforeach()
+  endif()
+
+  set(${SRCS})
+  foreach(FIL ${ARGN})
+    get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
+    get_filename_component(FIL_WE ${FIL} NAME_WE)
+
+    list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}_pb2.py")
+    add_custom_command(
+      OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}_pb2.py"
+      COMMAND  ${Protobuf_PROTOC_EXECUTABLE} --python_out ${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_include_path} ${ABS_FIL}
+      DEPENDS ${ABS_FIL} ${Protobuf_PROTOC_EXECUTABLE}
+      COMMENT "Running Python protocol buffer compiler on ${FIL}"
+      VERBATIM )
+  endforeach()
+
+  set(${SRCS} ${${SRCS}} PARENT_SCOPE)
+endfunction()
+
+# Environment
+
+# Backwards compatibility
+# Define camel case versions of input variables
+foreach(UPPER
+    PROTOBUF_SRC_ROOT_FOLDER
+    PROTOBUF_IMPORT_DIRS
+    PROTOBUF_DEBUG
+    PROTOBUF_LIBRARY
+    PROTOBUF_PROTOC_LIBRARY
+    PROTOBUF_INCLUDE_DIR
+    PROTOBUF_PROTOC_EXECUTABLE
+    PROTOBUF_LIBRARY_DEBUG
+    PROTOBUF_PROTOC_LIBRARY_DEBUG
+    PROTOBUF_LITE_LIBRARY
+    PROTOBUF_LITE_LIBRARY_DEBUG
+    )
+    if (DEFINED ${UPPER})
+        string(REPLACE "PROTOBUF_" "Protobuf_" Camel ${UPPER})
+        if (NOT DEFINED ${Camel})
+            set(${Camel} ${${UPPER}})
+        endif()
+    endif()
+endforeach()
+
+if(DEFINED Protobuf_SRC_ROOT_FOLDER)
+  message(AUTHOR_WARNING "Variable Protobuf_SRC_ROOT_FOLDER defined, but not"
+    " used in CONFIG mode")
+endif()
+
+include(SelectLibraryConfigurations)
+
 # Internal function: search for normal library as well as a debug one
 #    if the debug one is specified also include debug/optimized keywords
 #    in *_LIBRARIES variable
 function(_protobuf_find_libraries name filename)
-   get_target_property(${name}_LIBRARY lib${filename}
-     IMPORTED_LOCATION_RELEASE)
-   set(${name}_LIBRARY "${${name}_LIBRARY}" PARENT_SCOPE)
-   get_target_property(${name}_LIBRARY_DEBUG lib${filename}
-     IMPORTED_LOCATION_DEBUG)
-   set(${name}_LIBRARY_DEBUG "${${name}_LIBRARY_DEBUG}" PARENT_SCOPE)
+  if(${name}_LIBRARIES)
+    # Use result recorded by a previous call.
+  elseif(${name}_LIBRARY)
+    # Honor cache entry used by CMake 3.5 and lower.
+    set(${name}_LIBRARIES "${${name}_LIBRARY}" PARENT_SCOPE)
+  else()
+    get_target_property(_aliased protobuf::lib${filename} ALIASED_TARGET)
+    if(_aliased)
+        set(${name}_LIBRARY_RELEASE $<TARGET_FILE:protobuf::lib${filename}>)
+        set(${name}_LIBRARY_DEBUG $<TARGET_FILE:protobuf::lib${filename}>)
+    else()
+      get_target_property(${name}_LIBRARY_RELEASE protobuf::lib${filename}
+        LOCATION_RELEASE)
+      get_target_property(${name}_LIBRARY_DEBUG protobuf::lib${filename}
+        LOCATION_DEBUG)
+    endif()
 
-   if(NOT ${name}_LIBRARY_DEBUG)
-      # There is no debug library
-      set(${name}_LIBRARY_DEBUG ${${name}_LIBRARY} PARENT_SCOPE)
-      set(${name}_LIBRARIES     ${${name}_LIBRARY} PARENT_SCOPE)
-   else()
-      # There IS a debug library
-      set(${name}_LIBRARIES
-          optimized ${${name}_LIBRARY}
-          debug     ${${name}_LIBRARY_DEBUG}
-          PARENT_SCOPE
-      )
-   endif()
+    select_library_configurations(${name})
+    set(${name}_LIBRARY ${${name}_LIBRARY} PARENT_SCOPE)
+    set(${name}_LIBRARIES ${${name}_LIBRARIES} PARENT_SCOPE)
+  endif()
 endfunction()
 
 # Internal function: find threads library
@@ -107,33 +181,69 @@
 endif()
 
 # The Protobuf library
-_protobuf_find_libraries(PROTOBUF protobuf)
+_protobuf_find_libraries(Protobuf protobuf)
 
 # The Protobuf Lite library
-_protobuf_find_libraries(PROTOBUF_LITE protobuf-lite)
+_protobuf_find_libraries(Protobuf_LITE protobuf-lite)
 
 # The Protobuf Protoc Library
-_protobuf_find_libraries(PROTOBUF_PROTOC protoc)
+_protobuf_find_libraries(Protobuf_PROTOC protoc)
 
 if(UNIX)
   _protobuf_find_threads()
 endif()
 
 # Set the include directory
-set(PROTOBUF_INCLUDE_DIR "${_PROTOBUF_IMPORT_PREFIX}/@CMAKE_INSTALL_INCLUDEDIR@")
+get_target_property(Protobuf_INCLUDE_DIRS protobuf::libprotobuf
+  INTERFACE_INCLUDE_DIRECTORIES)
 
 # Set the protoc Executable
-get_target_property(PROTOBUF_PROTOC_EXECUTABLE protoc
-  IMPORTED_LOCATION_RELEASE)
-if(NOT PROTOBUF_PROTOC_EXECUTABLE)
-  get_target_property(PROTOBUF_PROTOC_EXECUTABLE protoc
-    IMPORTED_LOCATION_DEBUG)
+get_target_property(_aliased protobuf::protoc ALIASED_TARGET)
+if(_aliased)
+  if(POLICY CMP0026)
+    set(Protobuf_PROTOC_EXECUTABLE $<TARGET_FILE:protobuf::protoc>)
+  else()
+    get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
+      LOCATION)
+  endif()
+else()
+  get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
+    IMPORTED_LOCATION_RELEASE)
+  if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
+    get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
+      IMPORTED_LOCATION_DEBUG)
+  endif()
 endif()
 
+# Version info variable
+set(Protobuf_VERSION "@protobuf_VERSION@")
+
 include(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(PROTOBUF DEFAULT_MSG
-    PROTOBUF_LIBRARY PROTOBUF_INCLUDE_DIR)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Protobuf
+    REQUIRED_VARS Protobuf_LIBRARIES Protobuf_INCLUDE_DIRS
+    VERSION_VAR Protobuf_VERSION
+)
 
-if(PROTOBUF_FOUND)
-    set(PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIR})
-endif()
+# Backwards compatibility
+# Define upper case versions of output variables
+foreach(Camel
+    Protobuf_VERSION
+    Protobuf_SRC_ROOT_FOLDER
+    Protobuf_IMPORT_DIRS
+    Protobuf_DEBUG
+    Protobuf_INCLUDE_DIRS
+    Protobuf_LIBRARIES
+    Protobuf_PROTOC_LIBRARIES
+    Protobuf_LITE_LIBRARIES
+    Protobuf_LIBRARY
+    Protobuf_PROTOC_LIBRARY
+    Protobuf_INCLUDE_DIR
+    Protobuf_PROTOC_EXECUTABLE
+    Protobuf_LIBRARY_DEBUG
+    Protobuf_PROTOC_LIBRARY_DEBUG
+    Protobuf_LITE_LIBRARY
+    Protobuf_LITE_LIBRARY_DEBUG
+    )
+    string(TOUPPER ${Camel} UPPER)
+    set(${UPPER} ${${Camel}})
+endforeach()