# CMake file to replace the string contents in ONNX, Caffe, and Caffe2 proto. # Usage example: # cmake -DFILENAME=caffe2.pb.h -DLOCAL_PROTOBUF=ON -P ProtoBufPatch.cmake file(READ ${FILENAME} content) if(NOT SYSTEM_PROTOBUF) # protobuf-3.6.0 pattern string( REPLACE "::google::protobuf::internal::GetEmptyStringAlreadyInited" "GetEmptyStringAlreadyInited" content "${content}") # protobuf-3.8.0+ pattern string( REPLACE "::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited" "GetEmptyStringAlreadyInited" content "${content}") string( REPLACE "PROTOBUF_CONSTEXPR" "" content "${content}") # https://github.com/protocolbuffers/protobuf/commit/0400cca3236de1ca303af38bf81eab332d042b7c # changes PROTOBUF_CONSTEXPR to constexpr, which breaks windows # build. string( REGEX REPLACE "static constexpr ([^ ]+) ([^ ]+) =" "static \\1 const \\2 =" content "${content}") foreach(ns ${NAMESPACES}) # Insert "const ::std::string& GetEmptyStringAlreadyInited();" within # the namespace and make sure we only do it once in the file. Unfortunately # using string(REPLACE ...) doesn't work because it will replace at all # locations and there might be multiple declarations of the namespace # depending on how the proto is structured. set(search "namespace ${ns} {") string(LENGTH "${search}" search_len) string(FIND "${content}" "${search}" pos) if(${pos} GREATER -1) math(EXPR pos "${pos}+${search_len}") string(SUBSTRING "${content}" 0 ${pos} content_pre) string(SUBSTRING "${content}" ${pos} -1 content_post) string( CONCAT content "${content_pre}" " const ::std::string& GetEmptyStringAlreadyInited(); " "${content_post}") endif() endforeach() # The moving constructor is defined in the header file, which will cause # a link error that claims that the vftable is not found. Luckily, we # could move the definition into the source file to solve the problem. list(LENGTH NAMESPACES ns_count) if("${FILENAME}" MATCHES ".pb.h" AND ns_count EQUAL 1) string(REPLACE ".pb.h" ".pb.cc" SOURCE_FILENAME ${FILENAME}) file(READ ${SOURCE_FILENAME} content_cc_origin) string(REGEX MATCHALL "([a-zA-Z_]+)\\([a-zA-Z_]+&& from\\) noexcept[^}]*}" content_cc "${content}") string(REGEX REPLACE "};" "}\n" content_cc "${content_cc}") string(REGEX REPLACE "([a-zA-Z_]+)\\([a-zA-Z_]+&& from\\) noexcept" " \\1::\\1(\\1&& from) noexcept" content_cc "${content_cc}") set(content_cc "${content_cc_origin}\nnamespace ${NAMESPACES} {\n#if LANG_CXX11\n${content_cc}\n#endif\n}") string(REGEX REPLACE "([a-zA-Z_]+)\\([a-zA-Z_]+&& from\\) noexcept([^}]*)}" "\\1(\\1&& from) noexcept;" content "${content}") file(WRITE ${SOURCE_FILENAME} "${content_cc}") endif() endif(NOT SYSTEM_PROTOBUF) # constexpr int TensorBoundShape_DimType_DimType_ARRAYSIZE = TensorBoundShape_DimType_DimType_MAX + 1; # throws # error: more than one operator "+" matches these operands: # built-in operator "arithmetic + arithmetic" # function "c10::operator+(int, c10::BFloat16)" # function "c10::operator+(c10::BFloat16, int)" # function "c10::operator+(int, c10::Half)" # function "c10::operator+(c10::Half, int)" # operand types are: const caffe2::ExternalDataProto_SourceType + int string( REGEX REPLACE "constexpr ([^ ]+) ([^ ]+_ARRAYSIZE) = ([^ ]+_MAX) \\+ 1;" "constexpr \\1 \\2 = static_cast<\\1>(\\3) + 1;" content "${content}") file(WRITE ${FILENAME} "${content}")