xref: /aosp_15_r20/external/pytorch/cmake/ProtoBufPatch.cmake (revision da0073e96a02ea20f0ac840b70461e3646d07c45)
1# CMake file to replace the string contents in ONNX, Caffe, and Caffe2 proto.
2# Usage example:
3#   cmake -DFILENAME=caffe2.pb.h -DLOCAL_PROTOBUF=ON -P ProtoBufPatch.cmake
4
5file(READ ${FILENAME} content)
6
7if(NOT SYSTEM_PROTOBUF)
8  # protobuf-3.6.0 pattern
9  string(
10    REPLACE
11    "::google::protobuf::internal::GetEmptyStringAlreadyInited"
12    "GetEmptyStringAlreadyInited"
13    content
14    "${content}")
15
16  # protobuf-3.8.0+ pattern
17  string(
18    REPLACE
19    "::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited"
20    "GetEmptyStringAlreadyInited"
21    content
22    "${content}")
23
24  string(
25    REPLACE
26    "PROTOBUF_CONSTEXPR"
27    ""
28    content
29    "${content}")
30
31  # https://github.com/protocolbuffers/protobuf/commit/0400cca3236de1ca303af38bf81eab332d042b7c
32  # changes PROTOBUF_CONSTEXPR to constexpr, which breaks windows
33  # build.
34  if(MSVC)
35    string(
36      REGEX REPLACE
37      "static constexpr ([^ ]+) ([^ ]+) ="
38      "static \\1 const \\2 ="
39      content
40      "${content}")
41  endif()
42
43  foreach(ns ${NAMESPACES})
44    # Insert "const ::std::string& GetEmptyStringAlreadyInited();" within
45    # the namespace and make sure we only do it once in the file. Unfortunately
46    # using string(REPLACE ...) doesn't work because it will replace at all
47    # locations and there might be multiple declarations of the namespace
48    # depending on how the proto is structured.
49    set(search "namespace ${ns} {")
50    string(LENGTH "${search}" search_len)
51    string(FIND "${content}" "${search}" pos)
52    if(${pos} GREATER -1)
53      math(EXPR pos "${pos}+${search_len}")
54      string(SUBSTRING "${content}" 0 ${pos} content_pre)
55      string(SUBSTRING "${content}" ${pos} -1 content_post)
56      string(
57        CONCAT
58        content
59        "${content_pre}"
60        " const ::std::string& GetEmptyStringAlreadyInited(); "
61        "${content_post}")
62    endif()
63  endforeach()
64
65  # The moving constructor is defined in the header file, which will cause
66  # a link error that claims that the vftable is not found. Luckily, we
67  # could move the definition into the source file to solve the problem.
68  list(LENGTH NAMESPACES ns_count)
69  if("${FILENAME}" MATCHES ".pb.h" AND ns_count EQUAL 1)
70    string(REPLACE ".pb.h" ".pb.cc" SOURCE_FILENAME ${FILENAME})
71    file(READ ${SOURCE_FILENAME} content_cc_origin)
72
73    string(REGEX MATCHALL "([a-zA-Z_]+)\\([a-zA-Z_]+&& from\\) noexcept[^}]*}" content_cc "${content}")
74    string(REGEX REPLACE "};" "}\n" content_cc "${content_cc}")
75    string(REGEX REPLACE "([a-zA-Z_]+)\\([a-zA-Z_]+&& from\\) noexcept" "  \\1::\\1(\\1&& from) noexcept" content_cc "${content_cc}")
76    set(content_cc "${content_cc_origin}\nnamespace ${NAMESPACES} {\n#if LANG_CXX11\n${content_cc}\n#endif\n}")
77
78    string(REGEX REPLACE "([a-zA-Z_]+)\\([a-zA-Z_]+&& from\\) noexcept([^}]*)}" "\\1(\\1&& from) noexcept;" content "${content}")
79
80    file(WRITE ${SOURCE_FILENAME} "${content_cc}")
81  endif()
82endif(NOT SYSTEM_PROTOBUF)
83
84# constexpr int TensorBoundShape_DimType_DimType_ARRAYSIZE = TensorBoundShape_DimType_DimType_MAX + 1;
85# throws
86# error: more than one operator "+" matches these operands:
87#     built-in operator "arithmetic + arithmetic"
88#     function "c10::operator+(int, c10::BFloat16)"
89#     function "c10::operator+(c10::BFloat16, int)"
90#     function "c10::operator+(int, c10::Half)"
91#     function "c10::operator+(c10::Half, int)"
92#   operand types are: const caffe2::ExternalDataProto_SourceType + int
93string(
94  REGEX REPLACE
95  "constexpr ([^ ]+) ([^ ]+_ARRAYSIZE) = ([^ ]+_MAX) \\+ 1;"
96  "constexpr \\1 \\2 = static_cast<\\1>(\\3) + 1;"
97  content
98  "${content}")
99
100file(WRITE ${FILENAME} "${content}")
101