Are there some better ways to address warnings when compiling protocol buffer generated source file?
Asked Answered
R

4

17

For a simple proto file:

message Person {
  required int32 id = 1;
  required string name = 2;
  optional string email = 3;
}

It's been compiled by protoc.exe and the results are used in an also simple test project, which basically does nothing but including the protoc generated files.

I'm using the msvc10 to build the test project (x64), then it gave me a lot of warning:

Warning 1   warning C4244: 'return' : conversion from '__int64' to 'int', possible loss of data D:\Work\protobuf-trunk\src\google\protobuf\descriptor.h 1441    1   testProtobuf
...
Warning 11  warning C4267: 'argument' : conversion from 'size_t' to 'int', possible loss of data    D:\Work\protobuf-trunk\src\google\protobuf\unknown_field_set.h  142 1   testProtobuf
Warning 12  warning C4267: 'return' : conversion from 'size_t' to 'int', possible loss of data  D:\Work\protobuf-trunk\src\google\protobuf\unknown_field_set.h  237 1   testProtobuf
...
Warning 14  warning C4244: '=' : conversion from '__int64' to 'int', possible loss of data  D:\Work\protobuf-trunk\src\google\protobuf\io\coded_stream.h    902 1   testProtobuf
Warning 15  warning C4244: 'return' : conversion from '__int64' to 'int', possible loss of data D:\Work\protobuf-trunk\src\google\protobuf\io\coded_stream.h    1078    1   testProtobuf
Warning 16  warning C4267: 'argument' : conversion from 'size_t' to 'google::protobuf::uint32', possible loss of data   D:\Work\protobuf-trunk\src\google\protobuf\wire_format_lite_inl.h   663 1   testProtobuf
...
Warning 19  warning C4267: 'return' : conversion from 'size_t' to 'int', possible loss of data  D:\Work\protobuf-trunk\src\google\protobuf\wire_format_lite_inl.h   739 1   testProtobuf
Warning 20  warning C4267: 'argument' : conversion from 'size_t' to 'google::protobuf::uint32', possible loss of data   D:\Work\protobuf-trunk\src\google\protobuf\wire_format_lite_inl.h   742 1   testProtobuf
Warning 21  warning C4267: 'return' : conversion from 'size_t' to 'int', possible loss of data  D:\Work\protobuf-trunk\src\google\protobuf\wire_format_lite_inl.h   743 1   testProtobuf
Warning 22  warning C4267: 'argument' : conversion from 'size_t' to 'int', possible loss of data    D:\Work\testProtobuf\testProtobuf\person.pb.cc  211 1   testProtobuf
...
Warning 28  warning C4996: 'std::_Copy_impl': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators' C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xutility 2239    1   testProtobuf
Warning 29  warning C4996: 'std::_Copy_impl': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators' C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xutility 2239    1   testProtobuf

Is there any good way to address all of these warning? Any suggestions will be greatly appreciated.

ps. the libprotobuf project itself can be clean compiled by msvc10 without any warning.

[edit 2013/02/20]

working solution:

  1. set properties for those protoc generated .cc files:
    configuration properties -> c/c++ -> advanced -> disable specific warnings
Regrate answered 25/11, 2012 at 5:9 Comment(9)
Since protocol buffers appears to be an open source project you could fix protoc.exe to generate better code.Tybie
If you are sure the warnings are no problem, you can just switch them off with #pragma warning(disable: 4244, 4267, 4996). See dr-bill.net/CSC076/class_summaries/3-26/pragmas.htmPippin
@bames53, eh...that's a little out of my ability, i'm just curious how this issue is normally addressed since protocol buffer is so widely used and why there is no official upadte release sine last year.Regrate
@cxxl, i don't think it's a good idea to switch these warnings off since my own code could have these issues also. is there simple way to just switch them off for protocol buffer library?Regrate
You can switch them off at the beginning of a code block and switch them back on (with #pragma warning(enable:x,x,x) at the end of it. For more, see the link I posted.Pippin
About the PS: As far as Ì know the protobuf project itself has quite a few warnings turned of, as well...Schizomycete
How about using std::size_t instead of uint32? What do you need exactly 32 bits for?Squall
@cxxl, I just use the way you said, thanks~Regrate
@doomster, the files are generated by protoc.exe, i don't modify them too much.Regrate
I
5

You can hack the source of the protoc compiler to have it inject the pragmas into the generated files automatically.

In src/google/protobuf/compiler/cpp/cpp_file.cc in GenerateHeader(io::Printer* printer) around line 94, change the first printer->Print call to:

  // Generate top of header.
  printer->Print(
    "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
    "// source: $filename$\n"
    "\n"
    "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
    "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
    "\n"
    "#ifdef _MSC_VER\n"
    "#  pragma warning(push)\n"
    "#  pragma warning(disable: 4127 4244 4267)\n"
    "#endif\n"
    "\n"
    "#include <string>\n"
    "\n",
    "filename", file_->name(),
    "filename_identifier", filename_identifier);

Then at the end of the same function at around line 294, change the last printer->Print call to:

  printer->Print(
    "#ifdef _MSC_VER\n"
    "#  pragma warning(pop)\n"
    "#endif\n"
    "\n"
    "#endif  // PROTOBUF_$filename_identifier$__INCLUDED\n",
    "filename_identifier", filename_identifier);

Now you just need to compile the protoc target and run the new protoc.exe to have the pragmas in the generated headers.

Ingham answered 21/2, 2013 at 5:57 Comment(3)
I did the same trick for GenerateSource defined right after GenerateHeaders. Worked great, thanks!Vitascope
This is a very interesting solution. I wouldn't mind finding something a little more repeatable though. I hate to have to ask future developers to go patch protobuf before they build. Is there not a CMake solution that works? Somehow ignoring warnings only on specific files, as the OP suggested, but doing it via CMake instead of VS?Electrocautery
@ChuckClaunch I have a hacky solution, hoping someone's got a better one. #72053727Saurischian
R
7

A simple approach is to use a wrapper header for including the generated protobuf headers:

#ifndef MESSAGES_WRAPPER_H
#define MESSAGES_WRAPPER_H

#ifdef _MSC_VER
  #pragma warning(push)
  #pragma warning(disable: 4018 4100 4267)
#endif

#include "messages.pb.h"

#ifdef _MSC_VER
  #pragma warning(pop)
#endif

#endif // MESSAGES_WRAPPER_H
Rickert answered 23/8, 2019 at 9:37 Comment(1)
Warnings aren't coming from the header, they're coming from when the generated source files (.pb.cc) are compiled.Saurischian
I
5

You can hack the source of the protoc compiler to have it inject the pragmas into the generated files automatically.

In src/google/protobuf/compiler/cpp/cpp_file.cc in GenerateHeader(io::Printer* printer) around line 94, change the first printer->Print call to:

  // Generate top of header.
  printer->Print(
    "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
    "// source: $filename$\n"
    "\n"
    "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
    "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
    "\n"
    "#ifdef _MSC_VER\n"
    "#  pragma warning(push)\n"
    "#  pragma warning(disable: 4127 4244 4267)\n"
    "#endif\n"
    "\n"
    "#include <string>\n"
    "\n",
    "filename", file_->name(),
    "filename_identifier", filename_identifier);

Then at the end of the same function at around line 294, change the last printer->Print call to:

  printer->Print(
    "#ifdef _MSC_VER\n"
    "#  pragma warning(pop)\n"
    "#endif\n"
    "\n"
    "#endif  // PROTOBUF_$filename_identifier$__INCLUDED\n",
    "filename_identifier", filename_identifier);

Now you just need to compile the protoc target and run the new protoc.exe to have the pragmas in the generated headers.

Ingham answered 21/2, 2013 at 5:57 Comment(3)
I did the same trick for GenerateSource defined right after GenerateHeaders. Worked great, thanks!Vitascope
This is a very interesting solution. I wouldn't mind finding something a little more repeatable though. I hate to have to ask future developers to go patch protobuf before they build. Is there not a CMake solution that works? Somehow ignoring warnings only on specific files, as the OP suggested, but doing it via CMake instead of VS?Electrocautery
@ChuckClaunch I have a hacky solution, hoping someone's got a better one. #72053727Saurischian
W
1

I didn't much like hacking protoc sources due to maintenance burden, so I come up with simpler solution.

You are probably already generating the files using some kind of script as you need to pass many parameters to protoc, so it's is pretty easy to customize this script further.

I created powershell script that post-processes generated files and adds #include "Grpc.Header.h" at the start of the generated files, and #include "Grpc.Footer.h" at the end of said files. You can then customize those header files when placed in you project. Besides disabling warnings with #pragma warning, I could also introduce other changes easily when needed.

NOTE: in this example I generated additional #define that my project needed, as well as precompiled header support that is nice for MSVC. I'm leaving this in the example to illustrate what you can do but it can be safely removed. dllexport_decl=MYAPI allows to export protobuf classes in you dll project.

GenerateProto.ps1:

$ProjectDirectory = "My\Project\Directory\"
$ProtoDirectory = "My\Proto\Directory"

protoc --proto_path=$ProtoDirectory --cpp_out=dllexport_decl=MYAPI:$ProjectDirectory universe.proto

$Plugin = where.exe grpc_cpp_plugin

protoc --proto_path=$ProtoDirectory --grpc_out=$ProjectDirectory --plugin=protoc-gen-grpc=$Plugin universe.proto

foreach($File in Get-ChildItem $ProjectDirectory* -Include *.pb.cc, *.pb.h )
{
    $Content = Get-Content $File

    if( $File.FullName.EndsWith(".cc"))
    {
        Set-Content $File "#include `"pch.h`""
        Add-Content $File "#include `"Grpc.Header.h`""
    }
    else
    {
        Set-Content $File "#include `"Grpc.Header.h`""
    }

    Add-Content $File $Content
    Add-Content $File "#include `"Grpc.Footer.h`""
}

Grpc.Header.h:

#pragma warning(push)
#pragma warning(disable: 4251)

#ifdef API_EXPORT
#  define MYAPI __declspec(dllexport)
#else
#  define MYAPI __declspec(dllimport)
#endif

Grpc.Footer.h:

#pragma warning(pop)
Wallen answered 28/12, 2021 at 12:33 Comment(0)
S
1

I achieved this in CMake by splitting the sources into two lists and only applying warnings to my source files:

protobuf_generate_cpp(MYAPP_PROTO_SRCS MYAPP_PROTO_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/myapp.proto)

set(MYAPP_SRCS myapp.cpp)

set_source_files_properties${MYAPP_SRCS} PROPERTIES COMPILE_OPTIONS "-Wall;-Werror")

add_executable(myapp ${MYAPP_SRCS} ${MYAPP_PROTO_SRCS})
Saurischian answered 29/4, 2022 at 22:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.