diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index ac5fe9565c..5e818e09fd 100644 --- a/cmake/CMakeLists.txt +++ b/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("${CMAKE_CURRENT_LIST_DIR}/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() diff --git a/cmake/examples.cmake b/cmake/examples.cmake new file mode 100644 index 0000000000..f7d4d601cb --- /dev/null +++ b/cmake/examples.cmake @@ -0,0 +1,10 @@ +if(protobuf_VERBOSE) + message(STATUS "Protocol Buffers Examples Configuring...") +endif() + +# Add examples subproject +add_subdirectory(../examples examples) + +if(protobuf_VERBOSE) + message(STATUS "Protocol Buffers Examples Configuring done") +endif() diff --git a/cmake/install.cmake b/cmake/install.cmake index a5040b2271..6d7aa1e0da 100644 --- a/cmake/install.cmake +++ b/cmake/install.cmake @@ -87,22 +87,35 @@ if(NOT MSVC) else() set(CMAKE_INSTALL_CMAKEDIR "cmake" CACHE STRING "${_cmakedir_desc}") endif() +mark_as_advanced(CMAKE_INSTALL_CMAKEDIR) +# Import configuration install(EXPORT protobuf-targets DESTINATION "${CMAKE_INSTALL_CMAKEDIR}" NAMESPACE protobuf:: COMPONENT protobuf-export) 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) + +# Build tree import configuration (for import from subprojects) +if(NOT EXISTS "${protobuf_DIR}") + set(protobuf_DIR "${protobuf_BINARY_DIR}/${CMAKE_INSTALL_CMAKEDIR}") + set(Protobuf_DIR "${protobuf_DIR}") + file(COPY + "${CMAKE_CURRENT_LIST_DIR}/protobuf-options.cmake" + "${CMAKE_CURRENT_LIST_DIR}/protobuf-targets.cmake" + DESTINATION "${protobuf_DIR}") +endif() install(FILES - "${protobuf_BINARY_DIR}/protobuf-config.cmake" - "${protobuf_BINARY_DIR}/protobuf-config-version.cmake" - "${protobuf_BINARY_DIR}/protobuf-module.cmake" + "${CMAKE_CURRENT_LIST_DIR}/protobuf-options.cmake" + "${protobuf_BINARY_DIR}/${CMAKE_INSTALL_CMAKEDIR}/protobuf-config.cmake" + "${protobuf_BINARY_DIR}/${CMAKE_INSTALL_CMAKEDIR}/protobuf-config-version.cmake" + "${protobuf_BINARY_DIR}/${CMAKE_INSTALL_CMAKEDIR}/protobuf-module.cmake" DESTINATION "${CMAKE_INSTALL_CMAKEDIR}" COMPONENT protobuf-export) diff --git a/cmake/protobuf-config.cmake.in b/cmake/protobuf-config.cmake.in index f11796a47d..373155107d 100644 --- a/cmake/protobuf-config.cmake.in +++ b/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() diff --git a/cmake/protobuf-module.cmake.in b/cmake/protobuf-module.cmake.in index d81dc459b6..7ced934a42 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 @@ 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 $) + set(${name}_LIBRARY_DEBUG $) + 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 $) + 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() diff --git a/cmake/protobuf-options.cmake b/cmake/protobuf-options.cmake new file mode 100644 index 0000000000..99c85ebe67 --- /dev/null +++ b/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) diff --git a/cmake/protobuf-targets.cmake b/cmake/protobuf-targets.cmake new file mode 100644 index 0000000000..72660aaab7 --- /dev/null +++ b/cmake/protobuf-targets.cmake @@ -0,0 +1,17 @@ +# Library aliases +foreach(_library + libprotobuf-lite + libprotobuf + libprotoc) + if(TARGET ${_library} AND NOT TARGET protobuf::${_library}) + add_library(protobuf::${_library} ALIAS ${_library}) + endif() +endforeach() + +# Executable aliases +foreach(_executable + protoc) + if(TARGET ${_executable} AND NOT TARGET protobuf::${_executable}) + add_executable(protobuf::${_executable} ALIAS ${_executable}) + endif() +endforeach() diff --git a/cmake/tests.cmake b/cmake/tests.cmake index 76fdf8efdf..ec0d603064 100644 --- a/cmake/tests.cmake +++ b/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 diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 0000000000..b4796f1ce7 --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,79 @@ +# Minimum CMake required +cmake_minimum_required(VERSION 2.8.12) + +# Project +project(addressbook) + +# Find required protobuf package +find_package(protobuf 3 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) + + 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) + endif() + + install(TARGETS ${APP} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${APP}) + +endforeach()