| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- include_guard(DIRECTORY)
- #[[
- Add rules for creating Google Protobuf source files.
- qm_create_protobuf(<OUT>
- INPUT <files...>
- [OUTPUT_DIR <dir>]
- [TARGET <target>]
- [INCLUDE_DIRECTORIES <dirs...>]
- [OPTIONS <options...>]
- [DEPENDS <deps...>]
- [CREATE_ONCE]
- )
- INPUT: source files
- OUTPUT_DIR: output directory
- TARGET: add a custom target to run the generating command
- INCLUDE_DIRECTORIES: extra include directories
- OPTIONS: extra options passed to protobuf compiler
- DEPENDS: dependencies
- CREATE_ONCE: create proto code files at configure phase if not exist
- OUT: output source file paths
- #]]
- function(qm_create_protobuf _out)
- set(options CREATE_ONCE)
- set(oneValueArgs OUTPUT_DIR TARGET)
- set(multiValueArgs INPUT INCLUDE_DIRECTORIES OPTIONS DEPENDS)
- cmake_parse_arguments(FUNC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
- # Find `protoc`
- if(NOT PROTOC_EXECUTABLE)
- if(NOT TARGET protobuf::protoc)
- message(FATAL_ERROR "qm_create_protobuf: protobuf compiler not found. Add find_package(Protobuf) to CMake to enable.")
- endif()
- get_target_property(PROTOC_EXECUTABLE protobuf::protoc LOCATION)
- if(NOT PROTOC_EXECUTABLE)
- message(FATAL_ERROR "qm_create_protobuf: failed to get the location of `protoc`.")
- endif()
- # Cache value
- set(PROTOC_EXECUTABLE ${PROTOC_EXECUTABLE} PARENT_SCOPE)
- endif()
- if(NOT FUNC_INPUT)
- message(FATAL_ERROR "qm_create_protobuf: INPUT not specified.")
- endif()
- if(FUNC_OUTPUT_DIR)
- get_filename_component(_out_dir ${FUNC_OUTPUT_DIR} ABSOLUTE)
- file(MAKE_DIRECTORY ${_out_dir})
- else()
- set(_out_dir ${CMAKE_CURRENT_BINARY_DIR})
- endif()
- # Collect include paths and out files
- set(_include_options)
- set(_out_files)
- set(_input_names)
- foreach(_item IN LISTS FUNC_INCLUDE_DIRECTORIES)
- get_filename_component(_abs_path ${_item} ABSOLUTE)
- list(APPEND _include_options -I${_abs_path})
- endforeach()
- foreach(_item IN LISTS FUNC_INPUT)
- get_filename_component(_item ${_item} ABSOLUTE)
- get_filename_component(_abs_path ${_item} DIRECTORY)
- list(APPEND _include_options -I${_abs_path})
- endforeach()
- list(REMOVE_DUPLICATES _include_options)
- set(_create_once_warning)
- set(_create_once_warning_printed off)
- # Prepare for create once
- if(FUNC_CREATE_ONCE)
- # Check if options contain generator expressions
- foreach(_opt IN LISTS _include_options LISTS FUNC_OPTIONS)
- string(GENEX_STRIP "${_opt}" _no_genex)
- if(NOT _no_genex STREQUAL _opt)
- set(_create_once_warning "options contain generator expressions, skip generating source file now")
- break()
- endif()
- endforeach()
- endif()
- foreach(_item IN LISTS FUNC_INPUT)
- get_filename_component(_basename ${_item} NAME_WLE)
- list(APPEND _out_files ${_out_dir}/${_basename}.pb.h ${_out_dir}/${_basename}.pb.cc)
- get_filename_component(_name ${_item} NAME)
- list(APPEND _input_names ${_name})
- if(FUNC_CREATE_ONCE AND(NOT EXISTS ${_out_dir}/${_basename}.pb.h OR NOT EXISTS ${_out_dir}/${_basename}.pb.cc))
- if(_create_once_warning)
- if(NOT _create_once_warning_printed)
- message(WARNING "qm_create_protobuf: ${_create_once_warning}")
- set(_create_once_warning_printed on)
- endif()
- else()
- get_filename_component(_abs_file ${_item} ABSOLUTE)
- if(NOT EXISTS ${_abs_file})
- message(WARNING "qm_create_protobuf: input file \"${_name}\" is not available, skip generating source file now")
- else()
- message(STATUS "Protoc: Generating ${_basename}.pb.h, ${_basename}.pb.cc")
- execute_process(COMMAND
- ${PROTOC_EXECUTABLE} --cpp_out=${_out_dir} ${_include_options} ${FUNC_OPTIONS} ${_name}
- )
- endif()
- endif()
- endif()
- add_custom_command(
- OUTPUT ${_out_dir}/${_basename}.pb.h ${_out_dir}/${_basename}.pb.cc
- COMMAND ${PROTOC_EXECUTABLE} --cpp_out=${_out_dir} ${_include_options} ${FUNC_OPTIONS} ${_name}
- DEPENDS ${_item} ${FUNC_DEPENDS}
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
- VERBATIM
- )
- endforeach()
- if(FUNC_TARGET)
- if(NOT TARGET ${FUNC_TARGET})
- add_custom_target(${FUNC_TARGET})
- endif()
- add_dependencies(${FUNC_TARGET} ${_out_files})
- endif()
- set(${_out} ${_out_files} PARENT_SCOPE)
- endfunction()
|