|
|
|
function(protobuf_generate)
|
|
|
|
include(CMakeParseArguments)
|
|
|
|
|
|
|
|
set(_options APPEND_PATH)
|
Fix DEPENDENCIES in protobuf_generate() to accept multiple values instead of silently dropping
cmake: make DEPENDENCIES in protobuf_generate() a multi-value keyword (#19175)
It was previously a one-value keyword, so given
```cmake
protobuf_generate(
...
DEPENDENCIES
a
b
)
```
`a` would be a dependency, and `b` would be discarded (or, more precisely, added to `protobuf_generate_UNPARSED_ARGUMENTS`).
This can be confirmed with the following changes:
```diff
diff --git a/cmake/protobuf-generate.cmake b/cmake/protobuf-generate.cmake
index 244407ee2..6dfbcef6d 100644
--- a/cmake/protobuf-generate.cmake
+++ b/cmake/protobuf-generate.cmake
@@ -10,6 +10,9 @@ function(protobuf_generate)
cmake_parse_arguments(protobuf_generate "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}")
+ message("Deps: ${protobuf_generate_DEPENDENCIES}")
+ message("Unparsed args: ${protobuf_generate_UNPARSED_ARGUMENTS}")
+
if(NOT protobuf_generate_PROTOS AND NOT protobuf_generate_TARGET)
message(SEND_ERROR "Error: protobuf_generate called without any targets or source files")
return()
diff --git a/cmake/tests.cmake b/cmake/tests.cmake
index 7976546fe..1cadf1e5a 100644
--- a/cmake/tests.cmake
+++ b/cmake/tests.cmake
@@ -27,6 +27,7 @@ foreach(proto_file ${lite_test_protos})
LANGUAGE cpp
OUT_VAR pb_generated_files
IMPORT_DIRS ${protobuf_SOURCE_DIR}/src
+ DEPENDENCIES a b
)
set(lite_test_proto_files ${lite_test_proto_files} ${pb_generated_files})
endforeach(proto_file)
```
Which printed "Deps: a" and "Unparsed args: b" for lite test files. With this change, it now prints "Deps: a;b" and "Unparsed args: ".
AFAIK, making `DEPENDENCIES` a multi-value keyword is mostly backwards-compatible; however, users who specified dependencies that were being ignored may be surprised to see that they are no longer ignored (which could cause build errors).
To prevent this kind of problem in the future, validating that `protobuf_generate_UNPARSED_ARGUMENTS` is empty could be useful, but to avoid potentially breaking more builds I did not do this in this PR.
Closes #19175
COPYBARA_INTEGRATE_REVIEW=https://github.com/protocolbuffers/protobuf/pull/19175 from 71:protobuf-generate-dependencies c998afa11a99e85560f612c92e09e69d29bc8c1a
PiperOrigin-RevId: 694186507
1 month ago
|
|
|
set(_singleargs LANGUAGE OUT_VAR EXPORT_MACRO PROTOC_OUT_DIR PLUGIN PLUGIN_OPTIONS PROTOC_EXE)
|
|
|
|
if(COMMAND target_sources)
|
|
|
|
list(APPEND _singleargs TARGET)
|
|
|
|
endif()
|
Fix DEPENDENCIES in protobuf_generate() to accept multiple values instead of silently dropping
cmake: make DEPENDENCIES in protobuf_generate() a multi-value keyword (#19175)
It was previously a one-value keyword, so given
```cmake
protobuf_generate(
...
DEPENDENCIES
a
b
)
```
`a` would be a dependency, and `b` would be discarded (or, more precisely, added to `protobuf_generate_UNPARSED_ARGUMENTS`).
This can be confirmed with the following changes:
```diff
diff --git a/cmake/protobuf-generate.cmake b/cmake/protobuf-generate.cmake
index 244407ee2..6dfbcef6d 100644
--- a/cmake/protobuf-generate.cmake
+++ b/cmake/protobuf-generate.cmake
@@ -10,6 +10,9 @@ function(protobuf_generate)
cmake_parse_arguments(protobuf_generate "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}")
+ message("Deps: ${protobuf_generate_DEPENDENCIES}")
+ message("Unparsed args: ${protobuf_generate_UNPARSED_ARGUMENTS}")
+
if(NOT protobuf_generate_PROTOS AND NOT protobuf_generate_TARGET)
message(SEND_ERROR "Error: protobuf_generate called without any targets or source files")
return()
diff --git a/cmake/tests.cmake b/cmake/tests.cmake
index 7976546fe..1cadf1e5a 100644
--- a/cmake/tests.cmake
+++ b/cmake/tests.cmake
@@ -27,6 +27,7 @@ foreach(proto_file ${lite_test_protos})
LANGUAGE cpp
OUT_VAR pb_generated_files
IMPORT_DIRS ${protobuf_SOURCE_DIR}/src
+ DEPENDENCIES a b
)
set(lite_test_proto_files ${lite_test_proto_files} ${pb_generated_files})
endforeach(proto_file)
```
Which printed "Deps: a" and "Unparsed args: b" for lite test files. With this change, it now prints "Deps: a;b" and "Unparsed args: ".
AFAIK, making `DEPENDENCIES` a multi-value keyword is mostly backwards-compatible; however, users who specified dependencies that were being ignored may be surprised to see that they are no longer ignored (which could cause build errors).
To prevent this kind of problem in the future, validating that `protobuf_generate_UNPARSED_ARGUMENTS` is empty could be useful, but to avoid potentially breaking more builds I did not do this in this PR.
Closes #19175
COPYBARA_INTEGRATE_REVIEW=https://github.com/protocolbuffers/protobuf/pull/19175 from 71:protobuf-generate-dependencies c998afa11a99e85560f612c92e09e69d29bc8c1a
PiperOrigin-RevId: 694186507
1 month ago
|
|
|
set(_multiargs PROTOS IMPORT_DIRS GENERATE_EXTENSIONS PROTOC_OPTIONS DEPENDENCIES)
|
|
|
|
|
|
|
|
cmake_parse_arguments(protobuf_generate "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}")
|
|
|
|
|
|
|
|
if(NOT protobuf_generate_PROTOS AND NOT protobuf_generate_TARGET)
|
|
|
|
message(SEND_ERROR "Error: protobuf_generate called without any targets or source files")
|
|
|
|
return()
|
|
|
|
endif()
|
|
|
|
|
|
|
|
if(NOT protobuf_generate_OUT_VAR AND NOT protobuf_generate_TARGET)
|
|
|
|
message(SEND_ERROR "Error: protobuf_generate called without a target or output variable")
|
|
|
|
return()
|
|
|
|
endif()
|
|
|
|
|
|
|
|
if(NOT protobuf_generate_LANGUAGE)
|
|
|
|
set(protobuf_generate_LANGUAGE cpp)
|
|
|
|
endif()
|
|
|
|
string(TOLOWER ${protobuf_generate_LANGUAGE} protobuf_generate_LANGUAGE)
|
|
|
|
|
|
|
|
if(NOT protobuf_generate_PROTOC_OUT_DIR)
|
|
|
|
set(protobuf_generate_PROTOC_OUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
|
|
|
endif()
|
|
|
|
|
|
|
|
if(protobuf_generate_EXPORT_MACRO AND protobuf_generate_LANGUAGE STREQUAL cpp)
|
|
|
|
set(_dll_export_decl "dllexport_decl=${protobuf_generate_EXPORT_MACRO}")
|
|
|
|
endif()
|
|
|
|
|
|
|
|
foreach(_option ${_dll_export_decl} ${protobuf_generate_PLUGIN_OPTIONS})
|
|
|
|
# append comma - not using CMake lists and string replacement as users
|
|
|
|
# might have semicolons in options
|
|
|
|
if(_plugin_options)
|
|
|
|
set( _plugin_options "${_plugin_options},")
|
|
|
|
endif()
|
|
|
|
set(_plugin_options "${_plugin_options}${_option}")
|
|
|
|
endforeach()
|
|
|
|
|
|
|
|
if(protobuf_generate_PLUGIN)
|
|
|
|
set(_plugin "--plugin=${protobuf_generate_PLUGIN}")
|
|
|
|
endif()
|
|
|
|
|
|
|
|
if(NOT protobuf_generate_GENERATE_EXTENSIONS)
|
|
|
|
if(protobuf_generate_LANGUAGE STREQUAL cpp)
|
|
|
|
set(protobuf_generate_GENERATE_EXTENSIONS .pb.h .pb.cc)
|
|
|
|
elseif(protobuf_generate_LANGUAGE STREQUAL python)
|
|
|
|
set(protobuf_generate_GENERATE_EXTENSIONS _pb2.py)
|
|
|
|
else()
|
|
|
|
message(SEND_ERROR "Error: protobuf_generate given unknown Language ${LANGUAGE}, please provide a value for GENERATE_EXTENSIONS")
|
|
|
|
return()
|
|
|
|
endif()
|
|
|
|
endif()
|
|
|
|
|
|
|
|
if(protobuf_generate_TARGET)
|
|
|
|
get_target_property(_source_list ${protobuf_generate_TARGET} SOURCES)
|
|
|
|
foreach(_file ${_source_list})
|
|
|
|
if(_file MATCHES "proto$")
|
|
|
|
list(APPEND protobuf_generate_PROTOS ${_file})
|
|
|
|
endif()
|
|
|
|
endforeach()
|
|
|
|
endif()
|
|
|
|
|
|
|
|
if(NOT protobuf_generate_PROTOS)
|
|
|
|
message(SEND_ERROR "Error: protobuf_generate could not find any .proto files")
|
|
|
|
return()
|
|
|
|
endif()
|
|
|
|
|
|
|
|
if(protobuf_generate_APPEND_PATH)
|
|
|
|
# Create an include path for each file specified
|
|
|
|
foreach(_file ${protobuf_generate_PROTOS})
|
|
|
|
get_filename_component(_abs_file ${_file} ABSOLUTE)
|
|
|
|
get_filename_component(_abs_dir ${_abs_file} DIRECTORY)
|
|
|
|
list(FIND _protobuf_include_path ${_abs_dir} _contains_already)
|
|
|
|
if(${_contains_already} EQUAL -1)
|
|
|
|
list(APPEND _protobuf_include_path -I ${_abs_dir})
|
|
|
|
endif()
|
|
|
|
endforeach()
|
|
|
|
endif()
|
|
|
|
|
|
|
|
if(NOT protobuf_generate_PROTOC_EXE)
|
|
|
|
# Default to using the CMake executable
|
|
|
|
set(protobuf_generate_PROTOC_EXE protobuf::protoc)
|
|
|
|
endif()
|
|
|
|
|
|
|
|
foreach(DIR ${protobuf_generate_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()
|
|
|
|
|
|
|
|
if(NOT _protobuf_include_path)
|
|
|
|
set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})
|
|
|
|
endif()
|
|
|
|
|
|
|
|
set(_generated_srcs_all)
|
|
|
|
foreach(_proto ${protobuf_generate_PROTOS})
|
|
|
|
get_filename_component(_abs_file ${_proto} ABSOLUTE)
|
|
|
|
get_filename_component(_abs_dir ${_abs_file} DIRECTORY)
|
|
|
|
|
|
|
|
get_filename_component(_file_full_name ${_proto} NAME)
|
|
|
|
string(FIND "${_file_full_name}" "." _file_last_ext_pos REVERSE)
|
|
|
|
string(SUBSTRING "${_file_full_name}" 0 ${_file_last_ext_pos} _basename)
|
|
|
|
|
|
|
|
set(_suitable_include_found FALSE)
|
|
|
|
foreach(DIR ${_protobuf_include_path})
|
|
|
|
if(NOT DIR STREQUAL "-I")
|
|
|
|
file(RELATIVE_PATH _rel_dir ${DIR} ${_abs_dir})
|
|
|
|
if(_rel_dir STREQUAL _abs_dir)
|
|
|
|
# When there is no relative path from DIR to _abs_dir (e.g. due to
|
|
|
|
# different drive letters on Windows), _rel_dir is equal to _abs_dir.
|
|
|
|
# Therefore, DIR is not a suitable include path and must be skipped.
|
|
|
|
continue()
|
|
|
|
endif()
|
|
|
|
string(FIND "${_rel_dir}" "../" _is_in_parent_folder)
|
|
|
|
if (NOT ${_is_in_parent_folder} EQUAL 0)
|
|
|
|
set(_suitable_include_found TRUE)
|
|
|
|
break()
|
|
|
|
endif()
|
|
|
|
endif()
|
|
|
|
endforeach()
|
|
|
|
|
|
|
|
if(NOT _suitable_include_found)
|
|
|
|
message(SEND_ERROR "Error: protobuf_generate could not find any correct proto include directory.")
|
|
|
|
return()
|
|
|
|
endif()
|
|
|
|
|
|
|
|
set(_generated_srcs)
|
|
|
|
foreach(_ext ${protobuf_generate_GENERATE_EXTENSIONS})
|
|
|
|
list(APPEND _generated_srcs "${protobuf_generate_PROTOC_OUT_DIR}/${_rel_dir}/${_basename}${_ext}")
|
|
|
|
endforeach()
|
|
|
|
list(APPEND _generated_srcs_all ${_generated_srcs})
|
|
|
|
|
|
|
|
set(_comment "Running ${protobuf_generate_LANGUAGE} protocol buffer compiler on ${_proto}")
|
|
|
|
if(protobuf_generate_PROTOC_OPTIONS)
|
|
|
|
set(_comment "${_comment}, protoc-options: ${protobuf_generate_PROTOC_OPTIONS}")
|
|
|
|
endif()
|
|
|
|
if(_plugin_options)
|
|
|
|
set(_comment "${_comment}, plugin-options: ${_plugin_options}")
|
|
|
|
endif()
|
|
|
|
|
|
|
|
add_custom_command(
|
|
|
|
OUTPUT ${_generated_srcs}
|
|
|
|
COMMAND ${protobuf_generate_PROTOC_EXE}
|
|
|
|
ARGS ${protobuf_generate_PROTOC_OPTIONS} --${protobuf_generate_LANGUAGE}_out ${_plugin_options}:${protobuf_generate_PROTOC_OUT_DIR} ${_plugin} ${_protobuf_include_path} ${_abs_file}
|
|
|
|
DEPENDS ${_abs_file} ${protobuf_PROTOC_EXE} ${protobuf_generate_DEPENDENCIES}
|
|
|
|
COMMENT ${_comment}
|
|
|
|
VERBATIM )
|
|
|
|
endforeach()
|
|
|
|
|
|
|
|
set_source_files_properties(${_generated_srcs_all} PROPERTIES GENERATED TRUE)
|
|
|
|
if(protobuf_generate_OUT_VAR)
|
|
|
|
set(${protobuf_generate_OUT_VAR} ${_generated_srcs_all} PARENT_SCOPE)
|
|
|
|
endif()
|
|
|
|
if(protobuf_generate_TARGET)
|
|
|
|
target_sources(${protobuf_generate_TARGET} PRIVATE ${_generated_srcs_all})
|
|
|
|
endif()
|
|
|
|
|
|
|
|
endfunction()
|