Browse Source

Merge pull request #1643 from yeswalrus/cmake-examples

Build examples in CMake
Feng Xiao 9 năm trước cách đây
mục cha
commit
dfe0c9ad38

+ 18 - 3
cmake/CMakeLists.txt

@@ -1,15 +1,19 @@
 # Minimum CMake required
 cmake_minimum_required(VERSION 2.8.12)
 
-# Project
-project(protobuf C CXX)
+if(protobuf_VERBOSE)
+  message(STATUS "Protocol Buffers Configuring...")
+endif()
 
 # CMake policies
 cmake_policy(SET CMP0022 NEW)
 
+# Project
+project(protobuf C CXX)
+
 # Options
-option(protobuf_VERBOSE "Enable for verbose output" OFF)
 option(protobuf_BUILD_TESTS "Build tests" ON)
+option(protobuf_BUILD_EXAMPLES "Build examples" OFF)
 if (BUILD_SHARED_LIBS)
   set(protobuf_BUILD_SHARED_LIBS_DEFAULT ON)
 else (BUILD_SHARED_LIBS)
@@ -25,6 +29,9 @@ endif (MSVC)
 option(protobuf_WITH_ZLIB "Build with zlib support" ${protobuf_WITH_ZLIB_DEFAULT})
 set(protobuf_DEBUG_POSTFIX "d"
   CACHE STRING "Default debug postfix")
+mark_as_advanced(protobuf_DEBUG_POSTFIX)
+# User options
+include(protobuf-options.cmake)
 
 # Path to main configure script
 set(protobuf_CONFIGURE_SCRIPT "../configure.ac")
@@ -151,3 +158,11 @@ if (protobuf_BUILD_TESTS)
 endif (protobuf_BUILD_TESTS)
 
 include(install.cmake)
+
+if (protobuf_BUILD_EXAMPLES)
+  include(examples.cmake)
+endif (protobuf_BUILD_EXAMPLES)
+
+if(protobuf_VERBOSE)
+    message(STATUS "Protocol Buffers Configuring done")
+endif()

+ 57 - 0
cmake/examples.cmake

@@ -0,0 +1,57 @@
+if(protobuf_VERBOSE)
+  message(STATUS "Protocol Buffers Examples Configuring...")
+endif()
+
+get_filename_component(examples_dir "../examples" ABSOLUTE)
+
+if(protobuf_VERBOSE)
+  message(STATUS "Protocol Buffers Examples Configuring done")
+endif()
+include(ExternalProject)
+
+# Internal utility function: Create a custom target representing a build of examples with custom options.
+function(add_examples_build NAME)
+  ExternalProject_Add(${NAME}
+    PREFIX ${NAME}
+    SOURCE_DIR "${examples_dir}"
+    BINARY_DIR ${NAME}
+    STAMP_DIR ${NAME}/logs
+    INSTALL_COMMAND "" #Skip
+    LOG_CONFIGURE 1
+    CMAKE_CACHE_ARGS "-Dprotobuf_MSVC_STATIC_RUNTIME:BOOL=${protobuf_MSVC_STATIC_RUNTIME}"
+                     "-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}"
+                     "-Dprotobuf_VERBOSE:BOOL=${protobuf_VERBOSE}"
+                     ${ARGN}
+  )
+  set_property(TARGET ${NAME} PROPERTY FOLDER "Examples")
+  set_property(TARGET ${NAME} PROPERTY EXCLUDE_FROM_ALL TRUE)
+endfunction()
+
+# Add examples as an external project.
+# sub_directory cannot be used because the find_package(protobuf) call would cause failures with redefined targets.
+add_examples_build(examples "-Dprotobuf_DIR:PATH=${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_CMAKEDIR}")
+add_dependencies(examples libprotobuf protoc)
+
+option(protobuf_BUILD_EXAMPLES_MULTITEST "Build Examples in multiple configurations. Useful for testing." OFF)
+mark_as_advanced(protobuf_BUILD_EXAMPLES_MULTITEST)
+if(protobuf_BUILD_EXAMPLES_MULTITEST)
+  set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+
+  #Build using the legacy compatiblity module.
+  add_examples_build(examples-legacy
+    "-Dprotobuf_DIR:PATH=${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_CMAKEDIR}"
+    "-Dprotobuf_MODULE_COMPATIBLE:BOOL=TRUE"
+  )
+  add_dependencies(examples-legacy libprotobuf protoc)
+
+  #Build using the installed library.
+  add_examples_build(examples-installed
+    "-Dprotobuf_DIR:PATH=${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_CMAKEDIR}"
+  )
+
+  #Build using the installed library in legacy compatiblity mode.
+  add_examples_build(examples-installed-legacy
+    "-Dprotobuf_DIR:PATH=${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_CMAKEDIR}"
+    "-Dprotobuf_MODULE_COMPATIBLE:BOOL=TRUE"
+  )
+endif()

+ 28 - 13
cmake/install.cmake

@@ -6,6 +6,7 @@ foreach(_library
   libprotoc)
   set_property(TARGET ${_library}
     PROPERTY INTERFACE_INCLUDE_DIRECTORIES
+    $<BUILD_INTERFACE:${protobuf_source_dir}/src>
     $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
   install(TARGETS ${_library} EXPORT protobuf-targets
     RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${_library}
@@ -80,29 +81,43 @@ foreach(_file ${nobase_dist_proto_DATA})
   endif()
 endforeach()
 
-# Export configuration
+# Install configuration
 set(_cmakedir_desc "Directory relative to CMAKE_INSTALL to install the cmake configuration files")
 if(NOT MSVC)
   set(CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/protobuf" CACHE STRING "${_cmakedir_desc}")
 else()
   set(CMAKE_INSTALL_CMAKEDIR "cmake" CACHE STRING "${_cmakedir_desc}")
 endif()
-
-install(EXPORT protobuf-targets
-  DESTINATION "${CMAKE_INSTALL_CMAKEDIR}"
-  NAMESPACE protobuf::
-  COMPONENT protobuf-export)
+mark_as_advanced(CMAKE_INSTALL_CMAKEDIR)
 
 configure_file(protobuf-config.cmake.in
-  protobuf-config.cmake @ONLY)
+  ${CMAKE_INSTALL_CMAKEDIR}/protobuf-config.cmake @ONLY)
 configure_file(protobuf-config-version.cmake.in
-  protobuf-config-version.cmake @ONLY)
+  ${CMAKE_INSTALL_CMAKEDIR}/protobuf-config-version.cmake @ONLY)
 configure_file(protobuf-module.cmake.in
-  protobuf-module.cmake @ONLY)
+  ${CMAKE_INSTALL_CMAKEDIR}/protobuf-module.cmake @ONLY)
+configure_file(protobuf-options.cmake
+  ${CMAKE_INSTALL_CMAKEDIR}/protobuf-options.cmake @ONLY)
+
+# Allows the build directory to be used as a find directory.
+export(TARGETS libprotobuf-lite libprotobuf libprotoc protoc
+  NAMESPACE protobuf::
+  FILE ${CMAKE_INSTALL_CMAKEDIR}/protobuf-targets.cmake
+)
 
-install(FILES
-  "${protobuf_BINARY_DIR}/protobuf-config.cmake"
-  "${protobuf_BINARY_DIR}/protobuf-config-version.cmake"
-  "${protobuf_BINARY_DIR}/protobuf-module.cmake"
+install(EXPORT protobuf-targets
   DESTINATION "${CMAKE_INSTALL_CMAKEDIR}"
+  NAMESPACE protobuf::
   COMPONENT protobuf-export)
+
+install(DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_CMAKEDIR}/
+  DESTINATION "${CMAKE_INSTALL_CMAKEDIR}"
+  COMPONENT protobuf-export
+  PATTERN protobuf-targets.cmake EXCLUDE
+)
+
+option(protobuf_INSTALL_EXAMPLES "Install the examples folder" OFF)
+if(protobuf_INSTALL_EXAMPLES)
+  install(DIRECTORY ../examples/ DESTINATION examples
+    COMPONENT protobuf-examples)
+endif()

+ 4 - 13
cmake/protobuf-config.cmake.in

@@ -1,19 +1,10 @@
-# Version info variables
-set(PROTOBUF_VERSION        "@protobuf_VERSION@")
-set(PROTOBUF_VERSION_STRING "@protobuf_VERSION_STRING@")
+# User options
+include("${CMAKE_CURRENT_LIST_DIR}/protobuf-options.cmake")
 
 # Imported targets
 include("${CMAKE_CURRENT_LIST_DIR}/protobuf-targets.cmake")
 
-# Compute the installation prefix relative to this file.
-get_filename_component(_PROTOBUF_IMPORT_PREFIX
-  "${_PROTOBUF_PACKAGE_PREFIX}" PATH)
-get_filename_component(_PROTOBUF_IMPORT_PREFIX
-  "${_PROTOBUF_IMPORT_PREFIX}" PATH)
-get_filename_component(_PROTOBUF_IMPORT_PREFIX
-  "${_PROTOBUF_IMPORT_PREFIX}" PATH)
-
 # CMake FindProtobuf module compatible file
-if(NOT DEFINED PROTOBUF_MODULE_COMPATIBLE OR "${PROTOBUF_MODULE_COMPATIBLE}")
-  include("${_PROTOBUF_PACKAGE_PREFIX}/protobuf-module.cmake")
+if(protobuf_MODULE_COMPATIBLE)
+  include("${CMAKE_CURRENT_LIST_DIR}/protobuf-module.cmake")
 endif()

+ 157 - 47
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 @@ function(PROTOBUF_GENERATE_CPP SRCS HDRS)
     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 @@ function(PROTOBUF_GENERATE_CPP SRCS HDRS)
     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 @@ function(PROTOBUF_GENERATE_CPP SRCS HDRS)
   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(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()
+  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()
+
+    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 @@ if(NOT DEFINED PROTOBUF_GENERATE_CPP_APPEND_PATH)
 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()
 
-include(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(PROTOBUF DEFAULT_MSG
-    PROTOBUF_LIBRARY PROTOBUF_INCLUDE_DIR)
+# Version info variable
+set(Protobuf_VERSION "@protobuf_VERSION@")
 
-if(PROTOBUF_FOUND)
-    set(PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIR})
-endif()
+include(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Protobuf
+    REQUIRED_VARS Protobuf_LIBRARIES Protobuf_INCLUDE_DIRS
+    VERSION_VAR Protobuf_VERSION
+)
+
+# 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()

+ 7 - 0
cmake/protobuf-options.cmake

@@ -0,0 +1,7 @@
+# Verbose output
+option(protobuf_VERBOSE "Enable for verbose output" OFF)
+mark_as_advanced(protobuf_VERBOSE)
+
+# FindProtobuf module compatibel
+option(protobuf_MODULE_COMPATIBLE "CMake build-in FindProtobuf.cmake module compatible" OFF)
+mark_as_advanced(protobuf_MODULE_COMPATIBLE)

+ 1 - 0
cmake/tests.cmake

@@ -4,6 +4,7 @@ endif()
 
 option(protobuf_ABSOLUTE_TEST_PLUGIN_PATH
   "Using absolute test_plugin path in tests" ON)
+mark_as_advanced(protobuf_ABSOLUTE_TEST_PLUGIN_PATH)
 
 include_directories(
   ${protobuf_source_dir}/gmock

+ 63 - 0
examples/CMakeLists.txt

@@ -0,0 +1,63 @@
+# Minimum CMake required
+cmake_minimum_required(VERSION 2.8.12)
+
+# Project
+project(protobuf-examples)
+
+# Find required protobuf package
+find_package(protobuf CONFIG REQUIRED)
+
+if(protobuf_VERBOSE)
+  message(STATUS "Using Protocol Buffers ${Protobuf_VERSION}")
+endif()
+
+set(CMAKE_INCLUDE_CURRENT_DIR TRUE)
+
+# http://www.cmake.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F
+if(MSVC AND protobuf_MSVC_STATIC_RUNTIME)
+  foreach(flag_var
+      CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
+      CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+    if(${flag_var} MATCHES "/MD")
+      string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
+    endif(${flag_var} MATCHES "/MD")
+  endforeach()
+endif()
+
+foreach(example add_person list_people)
+  set(${example}_SRCS ${example}.cc)
+  set(${example}_PROTOS addressbook.proto)
+
+  #Code Generation
+  if(protobuf_MODULE_COMPATIBLE) #Legacy Support
+    protobuf_generate_cpp(${example}_PROTO_SRCS ${example}_PROTO_HDRS ${${example}_PROTOS})
+    list(APPEND ${example}_SRCS ${${example}_PROTO_SRCS} ${${example}_PROTO_HDRS})
+  else()
+
+    foreach(proto_file ${${example}_PROTOS})
+      get_filename_component(proto_file_abs ${proto_file} ABSOLUTE)
+      get_filename_component(basename ${proto_file} NAME_WE)
+      set(generated_files ${basename}.pb.cc ${basename}.pb.h)
+      list(APPEND ${example}_SRCS ${generated_files})
+
+      add_custom_command(
+        OUTPUT ${generated_files}
+        COMMAND protobuf::protoc
+        ARGS --cpp_out ${CMAKE_CURRENT_BINARY_DIR} -I ${CMAKE_CURRENT_SOURCE_DIR} ${proto_file_abs}
+        COMMENT "Generating ${generated_files} from ${proto_file}"
+        VERBATIM
+      )
+    endforeach()
+  endif()
+
+  #Executable setup
+  set(executable_name ${example}_cpp)
+  add_executable(${executable_name} ${${example}_SRCS} ${${example}_PROTOS})
+  if(protobuf_MODULE_COMPATIBLE) #Legacy mode
+    target_include_directories(${executable_name} PUBLIC ${PROTOBUF_INCLUDE_DIRS})
+    target_link_libraries(${executable_name} ${PROTOBUF_LIBRARIES})
+  else()
+    target_link_libraries(${executable_name} protobuf::libprotobuf)
+  endif()
+
+endforeach()