Commit 71556295 authored by Konstantin Podsvirov's avatar Konstantin Podsvirov

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.
parent 20b53254
# 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()
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()
......@@ -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)
# 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()
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()
# 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)
# 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()
......@@ -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
......
# 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()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment