1# User options 2include("${CMAKE_CURRENT_LIST_DIR}/protobuf-options.cmake") 3 4# Depend packages 5@_protobuf_FIND_ZLIB@ 6 7# Imported targets 8include("${CMAKE_CURRENT_LIST_DIR}/protobuf-targets.cmake") 9 10function(protobuf_generate) 11 include(CMakeParseArguments) 12 13 set(_options APPEND_PATH) 14 set(_singleargs LANGUAGE OUT_VAR EXPORT_MACRO PROTOC_OUT_DIR PLUGIN PLUGIN_OPTIONS) 15 if(COMMAND target_sources) 16 list(APPEND _singleargs TARGET) 17 endif() 18 set(_multiargs PROTOS IMPORT_DIRS GENERATE_EXTENSIONS PROTOC_OPTIONS) 19 20 cmake_parse_arguments(protobuf_generate "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}") 21 22 if(NOT protobuf_generate_PROTOS AND NOT protobuf_generate_TARGET) 23 message(SEND_ERROR "Error: protobuf_generate called without any targets or source files") 24 return() 25 endif() 26 27 if(NOT protobuf_generate_OUT_VAR AND NOT protobuf_generate_TARGET) 28 message(SEND_ERROR "Error: protobuf_generate called without a target or output variable") 29 return() 30 endif() 31 32 if(NOT protobuf_generate_LANGUAGE) 33 set(protobuf_generate_LANGUAGE cpp) 34 endif() 35 string(TOLOWER ${protobuf_generate_LANGUAGE} protobuf_generate_LANGUAGE) 36 37 if(NOT protobuf_generate_PROTOC_OUT_DIR) 38 set(protobuf_generate_PROTOC_OUT_DIR ${CMAKE_CURRENT_BINARY_DIR}) 39 endif() 40 41 if(protobuf_generate_EXPORT_MACRO AND protobuf_generate_LANGUAGE STREQUAL cpp) 42 set(_dll_export_decl "dllexport_decl=${protobuf_generate_EXPORT_MACRO}") 43 endif() 44 45 foreach(_option ${_dll_export_decl} ${protobuf_generate_PLUGIN_OPTIONS}) 46 # append comma - not using CMake lists and string replacement as users 47 # might have semicolons in options 48 if(_plugin_options) 49 set( _plugin_options "${_plugin_options},") 50 endif() 51 set(_plugin_options "${_plugin_options}${_option}") 52 endforeach() 53 54 if(protobuf_generate_PLUGIN) 55 set(_plugin "--plugin=${protobuf_generate_PLUGIN}") 56 endif() 57 58 if(NOT protobuf_generate_GENERATE_EXTENSIONS) 59 if(protobuf_generate_LANGUAGE STREQUAL cpp) 60 set(protobuf_generate_GENERATE_EXTENSIONS .pb.h .pb.cc) 61 elseif(protobuf_generate_LANGUAGE STREQUAL python) 62 set(protobuf_generate_GENERATE_EXTENSIONS _pb2.py) 63 else() 64 message(SEND_ERROR "Error: protobuf_generate given unknown Language ${LANGUAGE}, please provide a value for GENERATE_EXTENSIONS") 65 return() 66 endif() 67 endif() 68 69 if(protobuf_generate_TARGET) 70 get_target_property(_source_list ${protobuf_generate_TARGET} SOURCES) 71 foreach(_file ${_source_list}) 72 if(_file MATCHES "proto$") 73 list(APPEND protobuf_generate_PROTOS ${_file}) 74 endif() 75 endforeach() 76 endif() 77 78 if(NOT protobuf_generate_PROTOS) 79 message(SEND_ERROR "Error: protobuf_generate could not find any .proto files") 80 return() 81 endif() 82 83 if(protobuf_generate_APPEND_PATH) 84 # Create an include path for each file specified 85 foreach(_file ${protobuf_generate_PROTOS}) 86 get_filename_component(_abs_file ${_file} ABSOLUTE) 87 get_filename_component(_abs_dir ${_abs_file} DIRECTORY) 88 list(FIND _protobuf_include_path ${_abs_dir} _contains_already) 89 if(${_contains_already} EQUAL -1) 90 list(APPEND _protobuf_include_path -I ${_abs_dir}) 91 endif() 92 endforeach() 93 endif() 94 95 foreach(DIR ${protobuf_generate_IMPORT_DIRS}) 96 get_filename_component(ABS_PATH ${DIR} ABSOLUTE) 97 list(FIND _protobuf_include_path ${ABS_PATH} _contains_already) 98 if(${_contains_already} EQUAL -1) 99 list(APPEND _protobuf_include_path -I ${ABS_PATH}) 100 endif() 101 endforeach() 102 103 if(NOT _protobuf_include_path) 104 set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR}) 105 endif() 106 107 set(_generated_srcs_all) 108 foreach(_proto ${protobuf_generate_PROTOS}) 109 get_filename_component(_abs_file ${_proto} ABSOLUTE) 110 get_filename_component(_abs_dir ${_abs_file} DIRECTORY) 111 112 get_filename_component(_file_full_name ${_proto} NAME) 113 string(FIND "${_file_full_name}" "." _file_last_ext_pos REVERSE) 114 string(SUBSTRING "${_file_full_name}" 0 ${_file_last_ext_pos} _basename) 115 116 set(_suitable_include_found FALSE) 117 foreach(DIR ${_protobuf_include_path}) 118 if(NOT DIR STREQUAL "-I") 119 file(RELATIVE_PATH _rel_dir ${DIR} ${_abs_dir}) 120 string(FIND "${_rel_dir}" "../" _is_in_parent_folder) 121 if (NOT ${_is_in_parent_folder} EQUAL 0) 122 set(_suitable_include_found TRUE) 123 break() 124 endif() 125 endif() 126 endforeach() 127 128 if(NOT _suitable_include_found) 129 message(SEND_ERROR "Error: protobuf_generate could not find any correct proto include directory.") 130 return() 131 endif() 132 133 set(_generated_srcs) 134 foreach(_ext ${protobuf_generate_GENERATE_EXTENSIONS}) 135 list(APPEND _generated_srcs "${protobuf_generate_PROTOC_OUT_DIR}/${_rel_dir}/${_basename}${_ext}") 136 endforeach() 137 list(APPEND _generated_srcs_all ${_generated_srcs}) 138 139 set(_comment "Running ${protobuf_generate_LANGUAGE} protocol buffer compiler on ${_proto}") 140 if(protobuf_generate_PROTOC_OPTIONS) 141 set(_comment "${_comment}, protoc-options: ${protobuf_generate_PROTOC_OPTIONS}") 142 endif() 143 if(_plugin_options) 144 set(_comment "${_comment}, plugin-options: ${_plugin_options}") 145 endif() 146 147 add_custom_command( 148 OUTPUT ${_generated_srcs} 149 COMMAND protobuf::protoc 150 ARGS ${protobuf_generate_PROTOC_OPTIONS} --${protobuf_generate_LANGUAGE}_out ${_plugin_options}:${protobuf_generate_PROTOC_OUT_DIR} ${_plugin} ${_protobuf_include_path} ${_abs_file} 151 DEPENDS ${_abs_file} protobuf::protoc 152 COMMENT ${_comment} 153 VERBATIM ) 154 endforeach() 155 156 set_source_files_properties(${_generated_srcs_all} PROPERTIES GENERATED TRUE) 157 if(protobuf_generate_OUT_VAR) 158 set(${protobuf_generate_OUT_VAR} ${_generated_srcs_all} PARENT_SCOPE) 159 endif() 160 if(protobuf_generate_TARGET) 161 target_sources(${protobuf_generate_TARGET} PRIVATE ${_generated_srcs_all}) 162 endif() 163 164endfunction() 165 166# CMake FindProtobuf module compatible file 167if(protobuf_MODULE_COMPATIBLE) 168 include("${CMAKE_CURRENT_LIST_DIR}/protobuf-module.cmake") 169endif() 170