С++ project in MS Visual studio. When adding a new feature - support of the grpc, it looked quite logic to me 1) add grpc in the system 2) create a bat file with command-line call of protoc and call it in pre-build event to generate pb.cc/h files out of proto files. Problem is to make protoc generate c++ files for all proto files, because the call of protoc <.proto> per each file brings errors when some imports are not found, and the call of protoc for all proto files at once (in one command) bings other error - some of the objects are defined twice. Is there any way to call protoc from bat file to generate c++ files when some of proto files are imported in some others?
I have following *.proto structure, where A.proto imports B, and Subscribe.proto imports A and B, and Service.proto imports Subscribe.
Content of A.proto is:
syntax = "proto3";
package control;
import "Common/B.proto";
message A {
string Name = 1;
repeated B bs = 2;
}
Content of B.proto is:
syntax = "proto3";
package control;
import "google/protobuf/timestamp.proto";
message B {
optional string AName = 1;
string Name = 2;
google.protobuf.Timestamp SendTime = 3;
BStatus Status = 4;
optional tValueType ValueType = 5;
oneof Value {
sint64 sintValue = 6;
uint64 uintValue = 7;
string textValue = 8;
google.protobuf.Timestamp timeValue = 9;
}
}
enum tValueType {
Unknown = 0;
Byte = 1;
Short = 2;
Ushort = 3;
Long = 4;
Ulong = 5;
Text = 6;
Time = 7;
}
enum BStatus {
Good = 0;
Bad = 1;
}
Content of Subscribe.proto is:
syntax = "proto3";
import "Common/A.proto";
package control;
message SubscribeRequest {
repeated A a = 1;
}
message SubscribeResponse {
repeated A a = 1;
}
and content of Service.proto:
syntax = "proto3";
import "Commands/Subscribe.proto";
import "google/protobuf/empty.proto";
package control;
service srv {
rpc Subscribe(SubscribeRequest) returns (SubscribeResponse) {}
}
Now I make a bat file in protos directory, to build C++ sources, with 2 variants:
Both cases bring me errors.
protoc.exe -I=. -I=./project1 --cpp_out=%out_cpp% -I=./project1/Common -I=./project1/Commands Subscribe.proto B.proto A.proto Service.proto
error:
D:\tmp\protos>c:\dev\vcpkg\installed\x64-windows\tools\protobuf\protoc.exe -I=. -I=./project1 --cpp_out=D:\tmp\protos\build -I=./project1/Common -I=./project1/Commands Subscribe.proto B.proto A.proto Service.proto
B.proto: "control.B.Value" is already defined in file "Common/B.proto".
B.proto: "control.B._AName" is already defined in file "Common/B.proto".
B.proto: "control.B._ValueType" is already defined in file "Common/B.proto".
B.proto:8:21: "control.B.AName" is already defined in file "Common/B.proto".
B.proto:9:12: "control.B.Name" is already defined in file "Common/B.proto".
B.proto:11:31: "control.B.SendTime" is already defined in file "Common/B.proto".
B.proto:12:17: "control.B.Status" is already defined in file "Common/B.proto".
B.proto:14:25: "control.B.ValueType" is already defined in file "Common/B.proto".
B.proto:16:16: "control.B.sintValue" is already defined in file "Common/B.proto".
B.proto:17:16: "control.B.uintValue" is already defined in file "Common/B.proto".
B.proto:18:16: "control.B.textValue" is already defined in file "Common/B.proto".
B.proto:19:35: "control.B.timeValue" is already defined in file "Common/B.proto".
B.proto:7:9: "control.B" is already defined in file "Common/B.proto".
B.proto:24:5: "control.Unknown" is already defined in file "Common/B.proto".
B.proto:24:5: Note that enum values use C++ scoping rules, meaning that enum values are siblings of their type, not children of it. Therefore, "Unknown" must be unique within "control", not just within "tValueType".
B.proto:25:5: "control.Byte" is already defined in file "Common/B.proto".
B.proto:25:5: Note that enum values use C++ scoping rules, meaning that enum values are siblings of their type, not children of it. Therefore, "Byte" must be unique within "control", not just within "tValueType".
B.proto:26:5: "control.Short" is already defined in file "Common/B.proto".
B.proto:26:5: Note that enum values use C++ scoping rules, meaning that enum values are siblings of their type, not children of it. Therefore, "Short" must be unique within "control", not just within "tValueType".
B.proto:27:5: "control.Ushort" is already defined in file "Common/B.proto".
B.proto:27:5: Note that enum values use C++ scoping rules, meaning that enum values are siblings of their type, not children of it. Therefore, "Ushort" must be unique within "control", not just within "tValueType".
B.proto:28:5: "control.Long" is already defined in file "Common/B.proto".
B.proto:28:5: Note that enum values use C++ scoping rules, meaning that enum values are siblings of their type, not children of it. Therefore, "Long" must be unique within "control", not just within "tValueType".
B.proto:29:5: "control.Ulong" is already defined in file "Common/B.proto".
B.proto:29:5: Note that enum values use C++ scoping rules, meaning that enum values are siblings of their type, not children of it. Therefore, "Ulong" must be unique within "control", not just within "tValueType".
B.proto:30:5: "control.Text" is already defined in file "Common/B.proto".
B.proto:30:5: Note that enum values use C++ scoping rules, meaning that enum values are siblings of their type, not children of it. Therefore, "Text" must be unique within "control", not just within "tValueType".
B.proto:31:5: "control.Time" is already defined in file "Common/B.proto".
B.proto:31:5: Note that enum values use C++ scoping rules, meaning that enum values are siblings of their type, not children of it. Therefore, "Time" must be unique within "control", not just within "tValueType".
B.proto:23:6: "control.tValueType" is already defined in file "Common/B.proto".
B.proto:35:5: "control.Good" is already defined in file "Common/B.proto".
B.proto:35:5: Note that enum values use C++ scoping rules, meaning that enum values are siblings of their type, not children of it. Therefore, "Good" must be unique within "control", not just within "BStatus".
B.proto:36:5: "control.Bad" is already defined in file "Common/B.proto".
B.proto:36:5: Note that enum values use C++ scoping rules, meaning that enum values are siblings of their type, not children of it. Therefore, "Bad" must be unique within "control", not just within "BStatus".
B.proto:34:6: "control.BStatus" is already defined in file "Common/B.proto".
B.proto:12:9: "control.BStatus" seems to be defined in "Common/B.proto", which is not imported by "B.proto". To use it here, please add the necessary import.
B.proto:14:14: "control.tValueType" seems to be defined in "Common/B.proto", which is not imported by "B.proto". To use it here, please add the necessary import.
set out_cpp=%cd%\build
mkdir %out_cpp%
call :treeProcess %cd%
goto :eof
:treeProcess
for %%f in (*.proto) do protoc.exe -I=. --cpp_out=%out_cpp% %%f
for /D %%d in (*) do (
cd %%d
call :treeProcess %%d
cd ..
)
exit /b
it brings some errors, and compile only Service.pb.h/cc and Tag.pb.h/cc (two other files are not compiled due to errors)
D:\tmp\protos>call :treeProcess D:\tmp\protos
D:\tmp\protos>for %f in (*.proto) do c:\dev\vcpkg\installed\x64-windows\tools\protobuf\protoc.exe -I=. --cpp_out=D:\tmp\protos\build %f
D:\tmp\protos>for / %d in (*) do (
cd %d
call :treeProcess %d
cd ..
)
D:\tmp\protos>(
cd build
call :treeProcess build
cd ..
)
D:\tmp\protos\build>for %f in (*.proto) do c:\dev\vcpkg\installed\x64-windows\tools\protobuf\protoc.exe -I=. --cpp_out=D:\tmp\protos\build %f
D:\tmp\protos\build>for / %d in (*) do (
cd %d
call :treeProcess %d
cd ..
)
D:\tmp\protos\build>exit /b
D:\tmp\protos>(
cd project1
call :treeProcess project1
cd ..
)
D:\tmp\protos\project1>for %f in (*.proto) do c:\dev\vcpkg\installed\x64-windows\tools\protobuf\protoc.exe -I=. --cpp_out=D:\tmp\protos\build %f
D:\tmp\protos\project1>c:\dev\vcpkg\installed\x64-windows\tools\protobuf\protoc.exe -I=. --cpp_out=D:\tmp\protos\build Service.proto
Service.proto:4:1: warning: Import google/protobuf/empty.proto is unused.
D:\tmp\protos\project1>for / %d in (*) do (
cd %d
call :treeProcess %d
cd ..
)
D:\tmp\protos\project1>(
cd Commands
call :treeProcess Commands
cd ..
)
D:\tmp\protos\project1\Commands>for %f in (*.proto) do c:\dev\vcpkg\installed\x64-windows\tools\protobuf\protoc.exe -I=. --cpp_out=D:\tmp\protos\build %f
D:\tmp\protos\project1\Commands>c:\dev\vcpkg\installed\x64-windows\tools\protobuf\protoc.exe -I=. --cpp_out=D:\tmp\protos\build Subscribe.proto
Common/A.proto: File not found.
Subscribe.proto:3:1: Import "Common/A.proto" was not found or had errors.
Subscribe.proto:8:14: "A" is not defined.
Subscribe.proto:12:14: "A" is not defined.
D:\tmp\protos\project1\Commands>for / %d in (*) do (
cd %d
call :treeProcess %d
cd ..
)
D:\tmp\protos\project1\Commands>exit /b
D:\tmp\protos\project1>(
cd Common
call :treeProcess Common
cd ..
)
D:\tmp\protos\project1\Common>for %f in (*.proto) do c:\dev\vcpkg\installed\x64-windows\tools\protobuf\protoc.exe -I=. --cpp_out=D:\tmp\protos\build %f
D:\tmp\protos\project1\Common>c:\dev\vcpkg\installed\x64-windows\tools\protobuf\protoc.exe -I=. --cpp_out=D:\tmp\protos\build A.proto
Common/B.proto: File not found.
A.proto:5:1: Import "Common/B.proto" was not found or had errors.
A.proto:9:14: "B" is not defined.
D:\tmp\protos\project1\Common>c:\dev\vcpkg\installed\x64-windows\tools\protobuf\protoc.exe -I=. --cpp_out=D:\tmp\protos\build B.proto
D:\tmp\protos\project1\Common>for / %d in (*) do (
cd %d
call :treeProcess %d
cd ..
)
D:\tmp\protos\project1\Common>exit /b
D:\tmp\protos\project1>exit /b
D:\tmp\protos>exit /b
I searched for hours, but did not find proper solution to generate all proto files properly. Is this possible at all from bat file under windows? Please advise how to do this. (under linux I did this using CMakeLists.txt with the exact identical content and structure)
After many attempts to make protoc working from batch file, I gave it up and switched to cmake .
so, cmake is the shortest way to generate source files from protos.