浏览代码

Use ExternalProject_Add to build the examples in a stand-alone fashion.

Walter Gray 9 年之前
父节点
当前提交
09f6a5c1d2
共有 2 个文件被更改,包括 93 次插入62 次删除
  1. 49 2
      cmake/examples.cmake
  2. 44 60
      examples/CMakeLists.txt

+ 49 - 2
cmake/examples.cmake

@@ -2,9 +2,56 @@ if(protobuf_VERBOSE)
   message(STATUS "Protocol Buffers Examples Configuring...")
 endif()
 
-# Add examples subproject
-add_subdirectory(../examples examples)
+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()

+ 44 - 60
examples/CMakeLists.txt

@@ -2,78 +2,62 @@
 cmake_minimum_required(VERSION 2.8.12)
 
 # Project
-project(addressbook)
+project(protobuf-examples)
 
 # Find required protobuf package
-find_package(protobuf 3 CONFIG REQUIRED)
+find_package(protobuf CONFIG REQUIRED)
 
 if(protobuf_VERBOSE)
   message(STATUS "Using Protocol Buffers ${Protobuf_VERSION}")
 endif()
 
-file(GLOB SRC_LIST "*.cc")
-
-file(GLOB PROTO_LIST "*.proto")
-
-#
-# Code generation
-#
-
-if(protobuf_MODULE_COMPATIBLE) # Old school
-
-  include_directories(${Protobuf_INCLUDE_DIRS})
-  protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS ${PROTO_LIST})
-
-else() # New style
-
-  set(PROTO_SRCS)
-  set(PROTO_HDRS)
-
-  foreach(FIL ${PROTO_LIST})
-
-    get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
-    get_filename_component(FIL_WE ${FIL} NAME_WE)
-
-    list(APPEND PROTO_SRCS "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc")
-    list(APPEND PROTO_HDRS "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h")
-
-    add_custom_command(
-      OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc"
-             "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h"
-      COMMAND protobuf::protoc
-      ARGS --cpp_out ${CMAKE_CURRENT_BINARY_DIR} -I ${CMAKE_CURRENT_SOURCE_DIR}
-        ${ABS_FIL}
-      DEPENDS ${ABS_FIL}
-      COMMENT "Running C++ protocol buffer compiler on ${FIL}"
-      VERBATIM)
+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()
 
-include_directories(${CMAKE_CURRENT_BINARY_DIR})
-
-include(GNUInstallDirs)
-
-foreach(FIL ${SRC_LIST})
-
-  get_filename_component(FIL_NAME_WE ${FIL} NAME_WE)
-
-  set(APP ${FIL_NAME_WE}_cpp)
-
-  add_executable(${APP} ${FIL} ${PROTO_SRCS} ${PROTO_HDRS})
-
-  #
-  # Link libraries
-  #
-
-  if(protobuf_MODULE_COMPATIBLE) # Old school
-    target_link_libraries(${APP} ${Protobuf_LIBRARIES})
-  else() # New style
-    target_link_libraries(${APP} protobuf::libprotobuf)
+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()
 
-  install(TARGETS ${APP}
-    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${APP})
+  #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()