diff --git a/cmake/examples.cmake b/cmake/examples.cmake index f7d4d601cb..5a2538e4aa 100644 --- a/cmake/examples.cmake +++ b/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() diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index b4796f1ce7..c9d4688530 100644 --- a/examples/CMakeLists.txt +++ b/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()