Adapted from here:
http://www.kieltech.de/uweswiki/Google%20Protocol%20Buffers
(Original copied here for posterity)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
#
# Qt qmake integration with Google Protocol Buffers compiler protoc
#
# To compile protocol buffers with qt qmake, specify PROTOS variable and
# include this file
#
# Example:
# LIBS += /usr/local/lib/libprotobuf.so
# PROTOS = a.proto b.proto
# include(protobuf.pri)
#
# By default protoc looks for .proto files (including the imported ones) in
# the current directory where protoc is run. If you need to include additional
# paths specify the PROTOPATH variable
#
PROTOPATH += .
PROTOPATH += ../Protocol
PROTOPATHS =
for(p, PROTOPATH):PROTOPATHS += --proto_path=$${p}
protobuf_decl.name = protobuf header
protobuf_decl.input = PROTOS
protobuf_decl.output = ${QMAKE_FILE_BASE}.pb.h
protobuf_decl.commands = protoc --cpp_out="." $${PROTOPATHS} ${QMAKE_FILE_NAME}
protobuf_decl.variable_out = GENERATED_FILES
QMAKE_EXTRA_COMPILERS += protobuf_decl
protobuf_impl.name = protobuf implementation
protobuf_impl.input = PROTOS
protobuf_impl.output = ${QMAKE_FILE_BASE}.pb.cc
protobuf_impl.depends = ${QMAKE_FILE_BASE}.pb.h
protobuf_impl.commands = $$escape_expand(\n)
protobuf_impl.variable_out = GENERATED_SOURCES
QMAKE_EXTRA_COMPILERS += protobuf_impl
|
The issue I have with this project include and extra compiler definition is that it places the generated protocol buffer classes in the build directory, which is not what I wanted.
So I modified the Protobuf.pri file to place the generated .pb.h and pb.cc output files back in the directory containing the .proto file, meaning I can use them more directly from other classes in that directory. I’m using a pretty flat directory hierarchy, though, so your mileage may vary. The nice thing also about the modified script is that you can refer to it from any subproject in a multi-project .pro file, and the relative paths should resolve automatically, with the generated files always finding their way home.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
message("Generating protocol buffer classes from .proto files.")
protobuf_decl.name = protobuf headers
protobuf_decl.input = PROTOS
protobuf_decl.output = ${QMAKE_FILE_IN_PATH}/${QMAKE_FILE_BASE}.pb.h
protobuf_decl.commands = protoc --cpp_out=${QMAKE_FILE_IN_PATH} --proto_path=${QMAKE_FILE_IN_PATH} ${QMAKE_FILE_NAME}
protobuf_decl.variable_out = HEADERS
QMAKE_EXTRA_COMPILERS += protobuf_decl
protobuf_impl.name = protobuf sources
protobuf_impl.input = PROTOS
protobuf_impl.output = ${QMAKE_FILE_IN_PATH}/${QMAKE_FILE_BASE}.pb.cc
protobuf_impl.depends = ${QMAKE_FILE_IN_PATH}/${QMAKE_FILE_BASE}.pb.h
protobuf_impl.commands = $$escape_expand(\n)
protobuf_impl.variable_out = SOURCES
QMAKE_EXTRA_COMPILERS += protobuf_impl
|
The various QMAKE_FILE_BASE, QMAKE_FILE_IN_PATH, and QMAKE_FILE_NAME variables are all undocumented, but I found some references to them here and here. Unfortunately, the official qmake reference leaves a lot to be desired, to the perpetual consternation of ambitious programmers.
Now, once you’ve added some protocol buffer .proto to your project, you’ll have to build the protoc compiler (on Linux or OS X anyway). After building the protoc protobuf compiler on Mac, you might have to copy the protoc executable to a directory in Qt Creator’s build environment PATH, which looks something like this:
/Users/someuser/Qt5.0.2/5.0.2/clang_64/bin:/usr/bin:/bin:/usr/sbin:/sbin
Unfortunately, by default, Qt Creator doesn’t include /usr/local/bin in its build environment PATH. And attempting to extend the PATH by doing $PATH:/usr/local/bin did not work for me.
So I copied my protoc to /usr/bin. You might be able to extend the PATH somehow to include /usr/local/bin, but I also wasn’t sure if this setting would carry over to other build environments (e.g. Windows or Linux), so I opted to just make protoc globally available and will probably do this in the other build environments as well.
Once you have the Protobuf.pri in place and included, and have added a PROTOS declaration to your .pro file, the build should now have a line where protoc is being run:
1
2
3
4
5
6
7
8
9
10
11
|
11:54:18: Running steps for project TestApp...
11:54:18: Configuration unchanged, skipping qmake step.
11:54:18: Starting: "/usr/bin/make"
cd Core/ && ( test -e Makefile || /Users/someuser/Qt5.0.2/5.0.2/clang_64/bin/qmake /Users/someuser/Core/Core.pro -spec macx-clang CONFIG+=debug CONFIG+=x86_64 CONFIG+=declarative_debug CONFIG+=qml_debug -o Makefile ) && /usr/bin/make -f Makefile
/Users/someuser/Qt5.0.2/5.0.2/clang_64/bin/qmake -spec macx-clang CONFIG+=debug CONFIG+=x86_64 CONFIG+=declarative_debug CONFIG+=qml_debug -o Makefile ../../Core/Core.pro
Project MESSAGE: Generating protocol buffer classes from .proto files.
protoc --cpp_out=../../Core --proto_path=../../Core ../../Core/Data.proto
cd Gui/ && ( test -e Makefile || /Users/someuser/Qt5.0.2/5.0.2/clang_64/bin/qmake /Users/someuser/Gui/Gui.pro -spec macx-clang CONFIG+=debug CONFIG+=x86_64 CONFIG+=declarative_debug CONFIG+=qml_debug -o Makefile ) && /usr/bin/make -f Makefile
make[1]: Nothing to be done for `first'.
11:54:19: The process "/usr/bin/make" exited normally.
11:54:19: Elapsed time: 00:00.
|
Note that the .variable_out settings in the qmake extra compiler definitions above mean that you don’t ever have to add the generated .pb.cc and .pb.h files to the project containing the .proto file. They are automatically added to the SOURCES and HEADERS variables when the protoc compile process runs. And they are automatically set to be cleaned when you do a project rebuild. If you do add the .pb.cc and .pb.h files to your .pro file, you’ll get duplicate make rules, and a warning that one of the make rules was ignored. Since you’re probably not going to edit the generated files anyway, it doesn’t matter much that they won’t be visible in the Qt Creator project file tree.
Don’t forget to link to the protobuf library!
This was what I was looking for. Thanks!