aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvan Komissarov <ABBAPOH@gmail.com>2018-08-10 01:28:06 +0300
committerIvan Komissarov <ABBAPOH@gmail.com>2018-11-22 11:20:38 +0000
commit68578a4bc3f1667530f674db8d01933775ebc4ff (patch)
tree99b801bdce1b955b44ea5ba8b30dddc903ccf9a0
parent428cc6188fb4f99bca8522530ed400357cfe38ec (diff)
Add protobuf.cpp and protobuf.objc modules
These modules implement google protobuf support for QBS for c++ and objective-c languages [ChangeLog] Added protobuf support for C++ and Objective-C. Fixes: QBS-563 Change-Id: I4bb7e0bdfc1e09ea26c0cd3d3739a741ff834e5d Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
-rw-r--r--doc/reference/modules/protobufcpp-module.qdoc91
-rw-r--r--doc/reference/modules/protobufobjc-module.qdoc103
-rw-r--r--examples/examples.qbs2
-rw-r--r--examples/protobuf/cpp/README.md13
-rw-r--r--examples/protobuf/cpp/addressbook.qbs18
-rw-r--r--examples/protobuf/cpp/main.cpp171
-rw-r--r--examples/protobuf/objc/README.md5
-rw-r--r--examples/protobuf/objc/addressbook.qbs15
-rw-r--r--examples/protobuf/objc/main.m171
-rw-r--r--examples/protobuf/shared/addressbook.proto51
-rw-r--r--share/qbs/imports/qbs/Probes/FrameworkProbe.qbs12
-rw-r--r--share/qbs/imports/qbs/Probes/LibraryProbe.qbs60
-rw-r--r--share/qbs/modules/protobuf/cpp/protobufcpp.qbs48
-rw-r--r--share/qbs/modules/protobuf/objc/protobufobjc.qbs70
-rw-r--r--share/qbs/modules/protobuf/protobuf.js111
-rw-r--r--share/qbs/modules/protobuf/protobufbase.qbs30
-rw-r--r--tests/auto/blackbox/testdata/protobuf/addressbook.proto51
-rw-r--r--tests/auto/blackbox/testdata/protobuf/addressbook_cpp.qbs24
-rw-r--r--tests/auto/blackbox/testdata/protobuf/addressbook_objc.qbs22
-rw-r--r--tests/auto/blackbox/testdata/protobuf/import-main.cpp38
-rw-r--r--tests/auto/blackbox/testdata/protobuf/import.proto6
-rw-r--r--tests/auto/blackbox/testdata/protobuf/import.qbs26
-rw-r--r--tests/auto/blackbox/testdata/protobuf/main.cpp58
-rw-r--r--tests/auto/blackbox/testdata/protobuf/main.m50
-rw-r--r--tests/auto/blackbox/testdata/protobuf/needs-import-dir-main.cpp38
-rw-r--r--tests/auto/blackbox/testdata/protobuf/needs-import-dir.proto6
-rw-r--r--tests/auto/blackbox/testdata/protobuf/needs-import-dir.qbs27
-rw-r--r--tests/auto/blackbox/testdata/protobuf/subdir/myenum.proto6
-rw-r--r--tests/auto/blackbox/tst_blackbox.cpp34
-rw-r--r--tests/auto/blackbox/tst_blackbox.h2
30 files changed, 1353 insertions, 6 deletions
diff --git a/doc/reference/modules/protobufcpp-module.qdoc b/doc/reference/modules/protobufcpp-module.qdoc
new file mode 100644
index 000000000..d4dd36f68
--- /dev/null
+++ b/doc/reference/modules/protobufcpp-module.qdoc
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \contentspage index.html
+ \qmltype protobuf.cpp
+ \inqmlmodule QbsModules
+ \since Qbs 1.13
+
+ \brief Provides support for protocol buffers for the C++ language.
+
+ The \c protobuf.cpp module provides support for generating C++ headers and
+ sources from proto definition files using the \c protoc tool.
+
+ \section2 Relevant File Tags
+
+ \table
+ \header
+ \li Tag
+ \li Auto-tagged File Names
+ \li Since
+ \li Description
+ \row
+ \li \c{"protobuf.input"}
+ \li \c{*.proto}
+ \li 1.13.0
+ \li Source files with this tag are considered inputs to the \c protoc compiler.
+ \endtable
+*/
+
+/*!
+ \qmlproperty string protobuf.cpp::protocBinary
+
+ The command which to invoke when compiling proto definition files.
+
+ \defaultvalue \c auto-detected
+*/
+
+/*!
+ \qmlproperty pathList protobuf.cpp::importPaths
+
+ The list of imports that are passed to the \c protoc tool via the \c --proto_path option.
+ These imports should contain the proto files - they are used to determine
+ the relative structure of the generated files.
+ \note The paths are passed to \c protoc in the same order as specified in this property and
+ \c protoc output may differ depending on that order.
+
+ \defaultvalue \c []
+*/
+
+/*!
+ \qmlproperty string protobuf.cpp::includePath
+
+ The path where protobuf C++ headers are located. Set this property to override the
+ default location.
+
+ \defaultvalue \c auto-detected
+*/
+
+/*!
+ \qmlproperty string protobuf.cpp::libraryPath
+
+ The path where the protobuf C++ library is located. Set this property to override the
+ default location.
+
+ \defaultvalue \c auto-detected
+*/
diff --git a/doc/reference/modules/protobufobjc-module.qdoc b/doc/reference/modules/protobufobjc-module.qdoc
new file mode 100644
index 000000000..02155f492
--- /dev/null
+++ b/doc/reference/modules/protobufobjc-module.qdoc
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \contentspage index.html
+ \qmltype protobuf.objc
+ \inqmlmodule QbsModules
+ \since Qbs 1.13
+
+ \brief Provides support for protocol buffers for the Objective-C language.
+
+ The \c protobuf.objc module provides support for generating Objective-C
+ headers and sources from proto definition files using the \c protoc tool.
+
+ \section2 Relevant File Tags
+
+ \table
+ \header
+ \li Tag
+ \li Auto-tagged File Names
+ \li Since
+ \li Description
+ \row
+ \li \c{"protobuf.input"}
+ \li \c{*.proto}
+ \li 1.13.0
+ \li Source files with this tag are considered inputs to the \c protoc compiler.
+ \endtable
+*/
+
+/*!
+ \qmlproperty string protobuf.objc::protocBinary
+
+ The command which to invoke when compiling proto definition files.
+
+ \defaultvalue \c auto-detected
+*/
+
+/*!
+ \qmlproperty pathList protobuf.cpp::importPaths
+
+ The list of imports that are passed to the \c protoc tool via the \c --proto_path option.
+ These imports should contain the proto files - they are used to determine
+ the relative structure of the generated files.
+ \note The paths are passed to \c protoc in the same order as specified in this property and
+ \c protoc output may differ depending on that order.
+
+ \defaultvalue \c []
+*/
+
+/*!
+ \qmlproperty string protobuf.objc::includePath
+
+ The path where protobuf Objective-C headers are located. Set this property
+ to override the default location.
+
+ \note If a \l{protobuf.objc::frameworkPath}{framework} is present, this property
+ has no effect.
+
+ \defaultvalue \c auto-detected
+*/
+
+/*!
+ \qmlproperty string protobuf.objc::libraryPath
+
+ \note If a \l{protobuf.objc::frameworkPath}{framework} is present, this property
+ has no effect.
+
+ \defaultvalue \c auto-detected
+*/
+
+/*!
+ \qmlproperty string protobuf.objc::frameworkPath
+
+ The path where \c Protobuf.framework is located. Set this property to override the
+ default location.
+
+ \defaultvalue \c auto-detected
+*/
diff --git a/examples/examples.qbs b/examples/examples.qbs
index 0e4e5052c..4e51bdbaf 100644
--- a/examples/examples.qbs
+++ b/examples/examples.qbs
@@ -62,5 +62,7 @@ Project {
"helloworld-minimal/hello.qbs",
"helloworld-qt/hello.qbs",
"install-bundle/install-bundle.qbs",
+ "protobuf/cpp/addressbook.qbs",
+ "protobuf/objc/addressbook.qbs",
]
}
diff --git a/examples/protobuf/cpp/README.md b/examples/protobuf/cpp/README.md
new file mode 100644
index 000000000..f0e1b1a93
--- /dev/null
+++ b/examples/protobuf/cpp/README.md
@@ -0,0 +1,13 @@
+### Addressbook c++ example
+
+This example shows how to build a cpp application that uses Google protobuf.
+
+In order to build this example, you'll need to have a protobuf headers and library installed in the system in locations where QBS can find them.
+
+On Linux, you can install a package to the system.
+
+On macOS, you can use brew or compile and install protobuf manually:
+- to /usr/local/
+- to any folder, say /Users/<USER>/protobuf. Then you'll need to set protobuf.libraryPath: "/Users/<USER>/protobuf/lib" and protobuf.includePath: "/Users/<USER>/protobuf/include"
+
+On Windows, you have to compile and install protobuf manually to any folder and use libraryPath and includePath as shown above
diff --git a/examples/protobuf/cpp/addressbook.qbs b/examples/protobuf/cpp/addressbook.qbs
new file mode 100644
index 000000000..bd5afd377
--- /dev/null
+++ b/examples/protobuf/cpp/addressbook.qbs
@@ -0,0 +1,18 @@
+import qbs
+
+CppApplication {
+ name: "addressbook_cpp"
+ consoleApplication: true
+ condition: protobuf.present
+
+ Depends { name: "cpp" }
+ cpp.cxxLanguageVersion: "c++11"
+
+ Depends { id: protobuf; name: "protobuf.cpp"; required: false }
+
+ files: [
+ "../shared/addressbook.proto",
+ "main.cpp",
+ "README.md",
+ ]
+}
diff --git a/examples/protobuf/cpp/main.cpp b/examples/protobuf/cpp/main.cpp
new file mode 100644
index 000000000..703a9d302
--- /dev/null
+++ b/examples/protobuf/cpp/main.cpp
@@ -0,0 +1,171 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <ctime>
+#include <fstream>
+#include <google/protobuf/util/time_util.h>
+#include <iostream>
+#include <string>
+
+#include "addressbook.pb.h"
+
+using google::protobuf::util::TimeUtil;
+
+int printUsage(char *argv0)
+{
+ std::cerr << "Usage: " << argv0 << "add|list ADDRESS_BOOK_FILE" << std::endl;
+ return -1;
+}
+
+std::string readString(const std::string &promt)
+{
+ std::string result;
+ std::cout << promt;
+ std::getline(std::cin, result);
+ return result;
+}
+
+// This function fills in a Person message based on user input.
+void promptForAddress(tutorial::Person* person)
+{
+ std::cout << "Enter person ID number: ";
+ int id;
+ std::cin >> id;
+ person->set_id(id);
+ std::cin.ignore(256, '\n');
+
+ *person->mutable_name() = readString("Enter name: ");
+
+ const auto email = readString("Enter email address (blank for none): ");
+ if (!email.empty())
+ person->set_email(email);
+
+ while (true) {
+ const auto number = readString("Enter a phone number (or leave blank to finish): ");
+ if (number.empty())
+ break;
+
+ tutorial::Person::PhoneNumber *phone_number = person->add_phones();
+ phone_number->set_number(number);
+
+ const auto type = readString("Is this a mobile, home, or work phone? ");
+ if (type == "mobile")
+ phone_number->set_type(tutorial::Person::MOBILE);
+ else if (type == "home")
+ phone_number->set_type(tutorial::Person::HOME);
+ else if (type == "work")
+ phone_number->set_type(tutorial::Person::WORK);
+ else
+ std::cout << "Unknown phone type. Using default." << std::endl;
+ }
+ *person->mutable_last_updated() = TimeUtil::SecondsToTimestamp(time(NULL));
+}
+
+// Iterates though all people in the AddressBook and prints info about them.
+void listPeople(const tutorial::AddressBook& address_book)
+{
+ for (int i = 0; i < address_book.people_size(); i++) {
+ const tutorial::Person& person = address_book.people(i);
+
+ std::cout << "Person ID: " << person.id() << std::endl;
+ std::cout << " Name: " << person.name() << std::endl;
+ if (person.email() != "") {
+ std::cout << " E-mail address: " << person.email() << std::endl;
+ }
+
+ for (int j = 0; j < person.phones_size(); j++) {
+ const tutorial::Person::PhoneNumber& phone_number = person.phones(j);
+
+ switch (phone_number.type()) {
+ case tutorial::Person::MOBILE:
+ std::cout << " Mobile phone #: ";
+ break;
+ case tutorial::Person::HOME:
+ std::cout << " Home phone #: ";
+ break;
+ case tutorial::Person::WORK:
+ std::cout << " Work phone #: ";
+ break;
+ default:
+ std::cout << " Unknown phone #: ";
+ break;
+ }
+ std::cout << phone_number.number() << std::endl;
+ }
+ if (person.has_last_updated()) {
+ std::cout << " Updated: " << TimeUtil::ToString(person.last_updated()) << std::endl;
+ }
+ }
+}
+
+int main(int argc, char* argv[]) {
+ // Verify that the version of the library that we linked against is
+ // compatible with the version of the headers we compiled against.
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+ if (argc != 3)
+ return printUsage(argv[0]);
+
+ tutorial::AddressBook address_book;
+
+ // Read the existing address book.
+ std::fstream input(argv[2], std::ios::in | std::ios::binary);
+ if (!input) {
+ std::cout << argv[2] << ": File not found." << std::endl;
+ } else if (!address_book.ParseFromIstream(&input)) {
+ std::cerr << "Failed to parse address book." << std::endl;
+ return -1;
+ }
+
+ const std::string mode(argv[1]);
+ if (mode == "add") {
+ // Add an address.
+ promptForAddress(address_book.add_people());
+
+ if (!input)
+ std::cout << "Creating a new file." << std::endl;
+
+ // Write the new address book back to disk.
+ std::fstream output(argv[2], std::ios::out | std::ios::trunc | std::ios::binary);
+ if (!address_book.SerializeToOstream(&output)) {
+ std::cerr << "Failed to write address book." << std::endl;
+ return -1;
+ }
+ } else if (mode == "list") {
+ listPeople(address_book);
+ } else {
+ return printUsage(argv[0]);
+ }
+
+ // Optional: Delete all global objects allocated by libprotobuf.
+ google::protobuf::ShutdownProtobufLibrary();
+
+ return 0;
+}
diff --git a/examples/protobuf/objc/README.md b/examples/protobuf/objc/README.md
new file mode 100644
index 000000000..c0fc7c0e5
--- /dev/null
+++ b/examples/protobuf/objc/README.md
@@ -0,0 +1,5 @@
+### Addressbook objc example
+
+This example shows how to build an objective-c application that uses Google protobuf.
+
+In order to build this example, you'll need to have a ProtocolBuffers library or framework installed in the system.
diff --git a/examples/protobuf/objc/addressbook.qbs b/examples/protobuf/objc/addressbook.qbs
new file mode 100644
index 000000000..f087113d9
--- /dev/null
+++ b/examples/protobuf/objc/addressbook.qbs
@@ -0,0 +1,15 @@
+import qbs
+
+CppApplication {
+ name: "addressbook_objc"
+ consoleApplication: true
+ condition: protobuf.present && qbs.targetOS.contains("darwin")
+
+ Depends { name: "cpp" }
+ Depends { id: protobuf; name: "protobuf.objc"; required: false }
+
+ files: [
+ "../shared/addressbook.proto",
+ "main.m",
+ ]
+}
diff --git a/examples/protobuf/objc/main.m b/examples/protobuf/objc/main.m
new file mode 100644
index 000000000..903799fca
--- /dev/null
+++ b/examples/protobuf/objc/main.m
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Ivan Komissarov
+** Contact: abbapoh@gmail.com
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#import "Addressbook.pbobjc.h"
+
+#import <Foundation/Foundation.h>
+
+int printUsage(char *argv0)
+{
+ NSString *programName = [[NSString alloc] initWithUTF8String:argv0];
+ NSLog(@"%@", [[NSString alloc] initWithFormat:@"Usage: %@ add|list ADDRESS_BOOK_FILE", programName]);
+ [programName release];
+ return -1;
+}
+
+NSString *readString(NSString *promt)
+{
+ NSLog(@"%@", promt);
+ NSFileHandle *inputFile = [NSFileHandle fileHandleWithStandardInput];
+ NSData *inputData = [inputFile availableData];
+ NSString *result = [[[NSString alloc]initWithData:inputData encoding:NSUTF8StringEncoding] autorelease];
+ result = [[result stringByTrimmingCharactersInSet:
+ [NSCharacterSet whitespaceAndNewlineCharacterSet]] autorelease];
+ return result;
+}
+
+// This function fills in a Person message based on user input.
+void promptForAddress(Person* person)
+{
+ person.id_p = [readString(@"Enter person ID number:") intValue];
+ person.name = readString(@"Enter name:");
+
+ NSString *email = readString(@"Enter email address (blank for none):");
+ if ([email length] != 0)
+ person.email = email;
+
+ while (true) {
+ NSString *number = readString(@"Enter a phone number (or leave blank to finish):");
+ if ([number length] == 0)
+ break;
+
+ Person_PhoneNumber* phoneNumber = [[Person_PhoneNumber alloc] init];
+ phoneNumber.number = number;
+
+ NSString *type = readString(@"Is this a mobile, home, or work phone?:");
+ NSLog(@"\"%@\"", type);
+ if ([type compare:@"mobile"] == NSOrderedSame)
+ phoneNumber.type = Person_PhoneType_Mobile;
+ else if ([type compare:@"home"] == NSOrderedSame)
+ phoneNumber.type = Person_PhoneType_Home;
+ else if ([type compare:@"work"] == NSOrderedSame)
+ phoneNumber.type = Person_PhoneType_Work;
+ else
+ NSLog(@"%@", @"Unknown phone type. Using default.");
+
+ [person.phonesArray addObject:phoneNumber];
+ }
+}
+
+// Iterates though all people in the AddressBook and prints info about them.
+void listPeople(AddressBook *addressBook)
+{
+ NSArray *people = addressBook.peopleArray;
+ for (unsigned i = 0; i < [people count]; i++) {
+ Person *person = [people objectAtIndex:i];
+
+ NSLog(@"%@", [[[NSString alloc] initWithFormat:@"Person ID: %d", person.id_p] autorelease]);
+ NSLog(@"%@", [[[NSString alloc] initWithFormat:@"Person name: %@", person.name] autorelease]);
+
+ if ([person.email length] != 0) {
+ NSLog(@"%@", [[[NSString alloc] initWithFormat:@"E-mail address: %@", person.email] autorelease]);
+ }
+
+ NSArray *phones = person.phonesArray;
+ for (unsigned j = 0; j < [phones count]; j++) {
+ Person_PhoneNumber *phoneNumber = [phones objectAtIndex:j];
+ NSString *phonePrefix;
+
+ switch (phoneNumber.type) {
+ case Person_PhoneType_Mobile:
+ phonePrefix = @"Mobile phone";
+ break;
+ case Person_PhoneType_Home:
+ phonePrefix = @"Home phone";
+ break;
+ case Person_PhoneType_Work:
+ phonePrefix = @"Work phone";
+ break;
+ default:
+ phonePrefix = @"Unknown phone";
+ break;
+ }
+
+ NSLog(@"%@", [[[NSString alloc] initWithFormat:@" %@ #: %@", phonePrefix, phoneNumber.number] autorelease]);
+ }
+ printf("\n");
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc != 3)
+ return printUsage(argv[0]);
+
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ AddressBook *addressBook;// = [AddressBook alloc];
+ NSString *filePath = [[[NSString alloc] initWithUTF8String:argv[2]] autorelease];
+
+ // Read the existing address book.
+ NSData *data = [NSData dataWithContentsOfFile:filePath];
+ if (!data) {
+ NSLog(@"%@", [[NSString alloc] initWithFormat:@"%@ : File not found.", filePath]);
+ addressBook = [[[AddressBook alloc] init] autorelease];
+ } else {
+ NSError *error;
+ addressBook = [AddressBook parseFromData:data error:&error];
+ if (!addressBook) {
+ NSLog(@"%@", @"Failed to parse address book.");
+ [pool drain];
+ return -1;
+ }
+ }
+
+ if (strcmp(argv[1], "add") == 0) {
+ // Add an address.
+ Person *person = [[Person alloc] init];
+ promptForAddress(person);
+ [addressBook.peopleArray addObject:person];
+
+ if (!data) {
+ NSLog(@"%@", @"Creating a new file.");
+ }
+ [[addressBook data] writeToFile:filePath atomically:YES];
+ } else if (strcmp(argv[1], "list") == 0) {
+ listPeople(addressBook);
+ } else {
+ [pool drain];
+ return printUsage(argv[0]);
+ }
+
+ [pool drain];
+ return 0;
+}
diff --git a/examples/protobuf/shared/addressbook.proto b/examples/protobuf/shared/addressbook.proto
new file mode 100644
index 000000000..b4b33b4c6
--- /dev/null
+++ b/examples/protobuf/shared/addressbook.proto
@@ -0,0 +1,51 @@
+// See README.txt for information and build instructions.
+//
+// Note: START and END tags are used in comments to define sections used in
+// tutorials. They are not part of the syntax for Protocol Buffers.
+//
+// To get an in-depth walkthrough of this file and the related examples, see:
+// https://developers.google.com/protocol-buffers/docs/tutorials
+
+// [START declaration]
+syntax = "proto3";
+package tutorial;
+
+import "google/protobuf/timestamp.proto";
+// [END declaration]
+
+// [START java_declaration]
+option java_package = "com.example.tutorial";
+option java_outer_classname = "AddressBookProtos";
+// [END java_declaration]
+
+// [START csharp_declaration]
+option csharp_namespace = "Google.Protobuf.Examples.AddressBook";
+// [END csharp_declaration]
+
+// [START messages]
+message Person {
+ string name = 1;
+ int32 id = 2; // Unique ID number for this person.
+ string email = 3;
+
+ enum PhoneType {
+ MOBILE = 0;
+ HOME = 1;
+ WORK = 2;
+ }
+
+ message PhoneNumber {
+ string number = 1;
+ PhoneType type = 2;
+ }
+
+ repeated PhoneNumber phones = 4;
+
+ google.protobuf.Timestamp last_updated = 5;
+}
+
+// Our address book file is just one of these.
+message AddressBook {
+ repeated Person people = 1;
+}
+// [END messages]
diff --git a/share/qbs/imports/qbs/Probes/FrameworkProbe.qbs b/share/qbs/imports/qbs/Probes/FrameworkProbe.qbs
index 544759150..da5557cc9 100644
--- a/share/qbs/imports/qbs/Probes/FrameworkProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/FrameworkProbe.qbs
@@ -29,12 +29,12 @@
****************************************************************************/
PathProbe {
- platformPaths: [
- "~/Library/Frameworks",
- "/usr/local/lib",
- "/Library/Frameworks",
- "/System/Library/Frameworks"
- ]
+ platformPaths: (qbs.sysroot ? [qbs.sysroot + "/System/Library/Frameworks"] : []).concat([
+ "~/Library/Frameworks",
+ "/usr/local/lib",
+ "/Library/Frameworks",
+ "/System/Library/Frameworks"
+ ])
nameFilter: {
return function(name) {
diff --git a/share/qbs/imports/qbs/Probes/LibraryProbe.qbs b/share/qbs/imports/qbs/Probes/LibraryProbe.qbs
new file mode 100644
index 000000000..b81a15dcb
--- /dev/null
+++ b/share/qbs/imports/qbs/Probes/LibraryProbe.qbs
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Ivan Komissarov.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+PathProbe {
+ nameSuffixes: {
+ if (qbs.targetOS.contains("windows"))
+ return [".lib"];
+ if (qbs.targetOS.contains("macos"))
+ return [".dylib", ".a"];
+ return [".so", ".a"];
+ }
+ platformPaths: qbs.targetOS.contains("unix") ? [
+ "/usr/lib",
+ "/usr/local/lib",
+ ] : []
+ nameFilter: {
+ if (qbs.targetOS.contains("unix")) {
+ return function(name) {
+ return "lib" + name;
+ }
+ } else {
+ return function(name) {
+ return name;
+ }
+ }
+ }
+ platformEnvironmentPaths: {
+ if (qbs.targetOS.contains("windows"))
+ return [ "PATH" ];
+ else
+ return [ "LIBRARY_PATH" ];
+ }
+}
diff --git a/share/qbs/modules/protobuf/cpp/protobufcpp.qbs b/share/qbs/modules/protobuf/cpp/protobufcpp.qbs
new file mode 100644
index 000000000..5cb3257d4
--- /dev/null
+++ b/share/qbs/modules/protobuf/cpp/protobufcpp.qbs
@@ -0,0 +1,48 @@
+import qbs
+import qbs.File
+import qbs.FileInfo
+import qbs.Probes
+import "../protobufbase.qbs" as ProtobufBase
+import "../protobuf.js" as HelperFunctions
+
+ProtobufBase {
+ property string includePath: includeProbe.path
+ property string libraryPath: libraryProbe.path
+
+ Depends { name: "cpp" }
+
+ cpp.libraryPaths: [libraryPath]
+ cpp.dynamicLibraries: qbs.targetOS.contains("unix") ? ["protobuf", "pthread"] : ["protobuf"]
+ cpp.includePaths: [outputDir, includePath]
+
+ Rule {
+ inputs: ["protobuf.input"]
+ outputFileTags: ["hpp", "cpp"]
+ outputArtifacts: {
+ return [
+ HelperFunctions.cppArtifact(input.protobuf.cpp, product, input, "hpp", ".pb.h"),
+ HelperFunctions.cppArtifact(input.protobuf.cpp, product, input, "cpp", ".pb.cc")
+ ];
+ }
+
+ prepare: HelperFunctions.doPrepare(input.protobuf.cpp, product, input, outputs, "cpp")
+ }
+
+ validate: {
+ baseValidate();
+ if (!HelperFunctions.checkPath(includePath))
+ throw "Can't find cpp protobuf include files. Please set the includePath property.";
+ if (!HelperFunctions.checkPath(libraryPath))
+ throw "Can't find cpp protobuf library. Please set the libraryPath property.";
+ }
+
+ Probes.IncludeProbe {
+ id: includeProbe
+ names: "google/protobuf/message.h"
+ }
+
+ Probes.LibraryProbe {
+ id: libraryProbe
+ names: "protobuf"
+ }
+}
diff --git a/share/qbs/modules/protobuf/objc/protobufobjc.qbs b/share/qbs/modules/protobuf/objc/protobufobjc.qbs
new file mode 100644
index 000000000..c252d9949
--- /dev/null
+++ b/share/qbs/modules/protobuf/objc/protobufobjc.qbs
@@ -0,0 +1,70 @@
+import qbs
+import qbs.File
+import qbs.FileInfo
+import qbs.Probes
+import "../protobufbase.qbs" as ProtobufBase
+import "../protobuf.js" as HelperFunctions
+
+ProtobufBase {
+ property string includePath: includeProbe.path
+ property string libraryPath: libraryProbe.path
+ property string frameworkPath: frameworkProbe.path
+
+ Depends { name: "cpp" }
+
+ // library build
+ Properties {
+ condition: !frameworkPath
+ cpp.includePaths: [outputDir, includePath]
+ cpp.libraryPaths: [libraryPath]
+ cpp.frameworks: ["Foundation"]
+ cpp.dynamicLibraries: ["ProtocolBuffers"]
+ }
+
+ // framework build
+ Properties {
+ condition: frameworkPath
+ cpp.includePaths: [outputDir]
+ cpp.frameworkPaths: [frameworkPath]
+ cpp.frameworks: ["Foundation", "Protobuf"]
+ cpp.defines: ["GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS"]
+ }
+
+ Rule {
+ inputs: ["protobuf.input"]
+ outputFileTags: ["hpp", "objc"]
+ outputArtifacts: {
+ return [
+ HelperFunctions.objcArtifact(input.protobuf.objc, product, input, "hpp", ".pbobjc.h"),
+ HelperFunctions.objcArtifact(input.protobuf.objc, product, input, "objc", ".pbobjc.m")
+ ];
+ }
+
+ prepare: HelperFunctions.doPrepare(input.protobuf.objc, product, input, outputs, "objc")
+ }
+
+ validate: {
+ baseValidate();
+ if (!HelperFunctions.checkPath(frameworkPath)) {
+ if (!HelperFunctions.checkPath(includePath))
+ throw "Can't find objective-c protobuf include files. Please set the includePath or frameworkPath property.";
+ if (!HelperFunctions.checkPath(libraryPath))
+ throw "Can't find objective-c protobuf library. Please set the libraryPath or frameworkPath property.";
+ }
+ }
+
+ Probes.IncludeProbe {
+ id: includeProbe
+ names: "GPBMessage.h"
+ }
+
+ Probes.LibraryProbe {
+ id: libraryProbe
+ names: "ProtocolBuffers"
+ }
+
+ Probes.FrameworkProbe {
+ id: frameworkProbe
+ names: ["Protobuf"]
+ }
+}
diff --git a/share/qbs/modules/protobuf/protobuf.js b/share/qbs/modules/protobuf/protobuf.js
new file mode 100644
index 000000000..576a5ec07
--- /dev/null
+++ b/share/qbs/modules/protobuf/protobuf.js
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Ivan Komissarov
+** Contact: abbapoh@gmail.com
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+var File = require("qbs.File");
+var FileInfo = require("qbs.FileInfo");
+
+var checkPath = function(path) {
+ return path && File.exists(path)
+};
+
+function toCamelCase(str){
+ return str.split('_').map(function(word, index) {
+ // If it is the first word make sure to lowercase all the chars.
+ if (index === 0) {
+ return word.toLowerCase();
+ }
+ // If it is not the first word only upper case the first char and lowercase the rest.
+ return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
+ }).join('');
+}
+
+function getOutputDir(module, product, input) {
+ var outputDir = module.outputDir;
+ var importPaths = module.importPaths;
+ if (importPaths.length !== 0) {
+ var canonicalInput = File.canonicalFilePath(FileInfo.path(input.filePath));
+ for (var i = 0; i < importPaths.length; ++i) {
+ path = File.canonicalFilePath(importPaths[i]);
+
+ if (canonicalInput.startsWith(path)) {
+ return outputDir + "/" + FileInfo.relativePath(path, canonicalInput);
+ }
+ }
+ }
+ return outputDir;
+}
+
+function cppArtifact(module, product, input, tag, suffix) {
+ var outputDir = getOutputDir(module, product, input);
+ return {
+ fileTags: [tag],
+ filePath: outputDir + "/" + FileInfo.baseName(input.fileName) + suffix,
+ cpp: {
+ includePaths: [].concat(input.cpp.includePaths, outputDir),
+ warningLevel: "none",
+ }
+ };
+}
+
+function objcArtifact(module, product, input, tag, suffix) {
+ var outputDir = getOutputDir(module, product, input);
+ return {
+ fileTags: [tag],
+ filePath: outputDir + "/" + toCamelCase(FileInfo.baseName(input.fileName)) + suffix,
+ cpp: {
+ includePaths: [].concat(input.cpp.includePaths, outputDir),
+ warningLevel: "none",
+ }
+ }
+}
+
+function doPrepare(module, product, input, outputs, lang)
+{
+ var outputDir = module.outputDir;
+ var args = [];
+
+ args.push("--" + lang + "_out", outputDir);
+
+ var importPaths = module.importPaths;
+ if (importPaths.length === 0)
+ importPaths = [FileInfo.path(input.filePath)];
+ importPaths.forEach(function(path) {
+ if (!FileInfo.isAbsolutePath(path))
+ path = FileInfo.joinPaths(product.sourceDirectory, path);
+ args.push("--proto_path", path);
+ });
+
+ args.push(input.filePath);
+
+ var cmd = new Command(module.protocBinary, args);
+ cmd.highlight = "codegen";
+ cmd.description = "generating " + lang + " files for " + input.fileName;
+ return [cmd];
+}
diff --git a/share/qbs/modules/protobuf/protobufbase.qbs b/share/qbs/modules/protobuf/protobufbase.qbs
new file mode 100644
index 000000000..1c2e68800
--- /dev/null
+++ b/share/qbs/modules/protobuf/protobufbase.qbs
@@ -0,0 +1,30 @@
+import qbs
+import qbs.File
+import qbs.FileInfo
+import qbs.Probes
+import "protobuf.js" as HelperFunctions
+
+Module {
+ property string protocBinary: protocProbe.filePath
+ property pathList importPaths: []
+
+ property string outputDir: product.buildDirectory + "/protobuf"
+ readonly property string protobufRoot: FileInfo.path(FileInfo.path(protocBinary))
+
+ readonly property var baseValidate: {
+ return function() {
+ if (!File.exists(protocBinary))
+ throw "Can't find protoc binary. Please set the protocBinary property or make sure it is found in PATH";
+ }
+ }
+
+ FileTagger {
+ patterns: ["*.proto"]
+ fileTags: ["protobuf.input"];
+ }
+
+ Probes.BinaryProbe {
+ id: protocProbe
+ names: ["protoc"]
+ }
+}
diff --git a/tests/auto/blackbox/testdata/protobuf/addressbook.proto b/tests/auto/blackbox/testdata/protobuf/addressbook.proto
new file mode 100644
index 000000000..b4b33b4c6
--- /dev/null
+++ b/tests/auto/blackbox/testdata/protobuf/addressbook.proto
@@ -0,0 +1,51 @@
+// See README.txt for information and build instructions.
+//
+// Note: START and END tags are used in comments to define sections used in
+// tutorials. They are not part of the syntax for Protocol Buffers.
+//
+// To get an in-depth walkthrough of this file and the related examples, see:
+// https://developers.google.com/protocol-buffers/docs/tutorials
+
+// [START declaration]
+syntax = "proto3";
+package tutorial;
+
+import "google/protobuf/timestamp.proto";
+// [END declaration]
+
+// [START java_declaration]
+option java_package = "com.example.tutorial";
+option java_outer_classname = "AddressBookProtos";
+// [END java_declaration]
+
+// [START csharp_declaration]
+option csharp_namespace = "Google.Protobuf.Examples.AddressBook";
+// [END csharp_declaration]
+
+// [START messages]
+message Person {
+ string name = 1;
+ int32 id = 2; // Unique ID number for this person.
+ string email = 3;
+
+ enum PhoneType {
+ MOBILE = 0;
+ HOME = 1;
+ WORK = 2;
+ }
+
+ message PhoneNumber {
+ string number = 1;
+ PhoneType type = 2;
+ }
+
+ repeated PhoneNumber phones = 4;
+
+ google.protobuf.Timestamp last_updated = 5;
+}
+
+// Our address book file is just one of these.
+message AddressBook {
+ repeated Person people = 1;
+}
+// [END messages]
diff --git a/tests/auto/blackbox/testdata/protobuf/addressbook_cpp.qbs b/tests/auto/blackbox/testdata/protobuf/addressbook_cpp.qbs
new file mode 100644
index 000000000..797d4174e
--- /dev/null
+++ b/tests/auto/blackbox/testdata/protobuf/addressbook_cpp.qbs
@@ -0,0 +1,24 @@
+import qbs
+
+CppApplication {
+ name: "addressbook_cpp"
+ consoleApplication: true
+ condition: protobuf.present
+
+ Depends { name: "cpp" }
+ cpp.cxxLanguageVersion: "c++11"
+
+ Depends { id: protobuf; name: "protobuf.cpp"; required: false }
+ Probe {
+ id: presentProbe
+ property bool hasModule: protobuf.present
+ configure: {
+ console.info("has protobuf: " + hasModule);
+ }
+ }
+
+ files: [
+ "addressbook.proto",
+ "main.cpp",
+ ]
+}
diff --git a/tests/auto/blackbox/testdata/protobuf/addressbook_objc.qbs b/tests/auto/blackbox/testdata/protobuf/addressbook_objc.qbs
new file mode 100644
index 000000000..9ee82c68f
--- /dev/null
+++ b/tests/auto/blackbox/testdata/protobuf/addressbook_objc.qbs
@@ -0,0 +1,22 @@
+import qbs
+
+CppApplication {
+ name: "addressbook_objc"
+ consoleApplication: true
+ condition: protobuf.present && qbs.targetOS.contains("darwin")
+
+ Depends { name: "cpp" }
+ Depends { id: protobuf; name: "protobuf.objc"; required: false }
+ Probe {
+ id: presentProbe
+ property bool hasModule: protobuf.present && qbs.targetOS.contains("darwin")
+ configure: {
+ console.info("has protobuf: " + hasModule);
+ }
+ }
+
+ files: [
+ "addressbook.proto",
+ "main.m",
+ ]
+}
diff --git a/tests/auto/blackbox/testdata/protobuf/import-main.cpp b/tests/auto/blackbox/testdata/protobuf/import-main.cpp
new file mode 100644
index 000000000..6d90cdf16
--- /dev/null
+++ b/tests/auto/blackbox/testdata/protobuf/import-main.cpp
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Ivan Komissarov
+** Contact: abbapoh@gmail.com
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include <import.pb.h>
+
+int main()
+{
+ MyMessage message;
+ message.set_msg("msg");
+ return 0;
+}
diff --git a/tests/auto/blackbox/testdata/protobuf/import.proto b/tests/auto/blackbox/testdata/protobuf/import.proto
new file mode 100644
index 000000000..d11e83b7a
--- /dev/null
+++ b/tests/auto/blackbox/testdata/protobuf/import.proto
@@ -0,0 +1,6 @@
+syntax = "proto2";
+import "subdir/myenum.proto";
+
+message MyMessage {
+ required string msg = 1;
+}
diff --git a/tests/auto/blackbox/testdata/protobuf/import.qbs b/tests/auto/blackbox/testdata/protobuf/import.qbs
new file mode 100644
index 000000000..b93e03a1e
--- /dev/null
+++ b/tests/auto/blackbox/testdata/protobuf/import.qbs
@@ -0,0 +1,26 @@
+import qbs
+
+CppApplication {
+ name: "app"
+ consoleApplication: true
+ condition: protobuf.cpp.present
+
+ protobuf.cpp.importPaths: [sourceDirectory]
+
+ cpp.cxxLanguageVersion: "c++11"
+
+ Depends { name: "protobuf.cpp"; required: false }
+ Probe {
+ id: presentProbe
+ property bool hasModule: protobuf.cpp.present
+ configure: {
+ console.info("has protobuf: " + hasModule);
+ }
+ }
+
+ files: [
+ "import.proto",
+ "import-main.cpp",
+ "subdir/myenum.proto",
+ ]
+}
diff --git a/tests/auto/blackbox/testdata/protobuf/main.cpp b/tests/auto/blackbox/testdata/protobuf/main.cpp
new file mode 100644
index 000000000..c93c46717
--- /dev/null
+++ b/tests/auto/blackbox/testdata/protobuf/main.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Ivan Komissarov
+** Contact: abbapoh@gmail.com
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include <google/protobuf/util/time_util.h>
+#include <string>
+
+#include "addressbook.pb.h"
+
+using google::protobuf::util::TimeUtil;
+
+int main(int /*argc*/, char* /*argv*/[]) {
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+ tutorial::AddressBook addressBook;
+
+ auto person = addressBook.add_people();
+ person->set_name("name");
+ person->set_id(1);
+ person->set_email("email");
+
+ auto phone_number = person->add_phones();
+ phone_number->set_number("number");
+ phone_number->set_type(tutorial::Person::MOBILE);
+
+ *person->mutable_last_updated() = TimeUtil::SecondsToTimestamp(time(nullptr));
+
+ google::protobuf::ShutdownProtobufLibrary();
+
+ return 0;
+}
+
diff --git a/tests/auto/blackbox/testdata/protobuf/main.m b/tests/auto/blackbox/testdata/protobuf/main.m
new file mode 100644
index 000000000..e9d7ce66a
--- /dev/null
+++ b/tests/auto/blackbox/testdata/protobuf/main.m
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Ivan Komissarov
+** Contact: abbapoh@gmail.com
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#import "Addressbook.pbobjc.h"
+
+int main(int argc, char* argv[])
+{
+ AddressBook *addressBook = [[AddressBook alloc] init];
+
+ Person *person = [[Person alloc] init];
+ person.name = @"name";
+ person.id_p = 1;
+ person.email = @"email";
+
+ Person_PhoneNumber *number = [[Person_PhoneNumber alloc] init];
+ number.number = @"number";
+ number.type = Person_PhoneType_Mobile;
+
+ [addressBook.peopleArray addObject:person];
+ [addressBook release];
+
+ return 0;
+}
diff --git a/tests/auto/blackbox/testdata/protobuf/needs-import-dir-main.cpp b/tests/auto/blackbox/testdata/protobuf/needs-import-dir-main.cpp
new file mode 100644
index 000000000..d6faf9e84
--- /dev/null
+++ b/tests/auto/blackbox/testdata/protobuf/needs-import-dir-main.cpp
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Ivan Komissarov
+** Contact: abbapoh@gmail.com
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include <needs-import-dir.pb.h>
+
+int main()
+{
+ MyMessage message;
+ message.set_msg("msg");
+ return 0;
+}
diff --git a/tests/auto/blackbox/testdata/protobuf/needs-import-dir.proto b/tests/auto/blackbox/testdata/protobuf/needs-import-dir.proto
new file mode 100644
index 000000000..0d0cb6578
--- /dev/null
+++ b/tests/auto/blackbox/testdata/protobuf/needs-import-dir.proto
@@ -0,0 +1,6 @@
+syntax = "proto2";
+import "myenum.proto";
+
+message MyMessage {
+ required string msg = 1;
+}
diff --git a/tests/auto/blackbox/testdata/protobuf/needs-import-dir.qbs b/tests/auto/blackbox/testdata/protobuf/needs-import-dir.qbs
new file mode 100644
index 000000000..e95421a9e
--- /dev/null
+++ b/tests/auto/blackbox/testdata/protobuf/needs-import-dir.qbs
@@ -0,0 +1,27 @@
+import qbs
+
+CppApplication {
+ name: "app"
+ consoleApplication: true
+ condition: protobuf.cpp.present
+
+ property path theImportDir
+ protobuf.cpp.importPaths: (theImportDir ? [theImportDir] : []).concat([sourceDirectory])
+
+ cpp.cxxLanguageVersion: "c++11"
+
+ Depends { name: "protobuf.cpp"; required: false }
+ Probe {
+ id: presentProbe
+ property bool hasModule: protobuf.cpp.present
+ configure: {
+ console.info("has protobuf: " + hasModule);
+ }
+ }
+
+ files: [
+ "needs-import-dir.proto",
+ "needs-import-dir-main.cpp",
+ "subdir/myenum.proto",
+ ]
+}
diff --git a/tests/auto/blackbox/testdata/protobuf/subdir/myenum.proto b/tests/auto/blackbox/testdata/protobuf/subdir/myenum.proto
new file mode 100644
index 000000000..0b82869fc
--- /dev/null
+++ b/tests/auto/blackbox/testdata/protobuf/subdir/myenum.proto
@@ -0,0 +1,6 @@
+syntax = "proto2";
+
+enum MyEnum {
+ VAL1 = 0;
+ VAL2 = 1;
+}
diff --git a/tests/auto/blackbox/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp
index 0302309fb..de0e2c26d 100644
--- a/tests/auto/blackbox/tst_blackbox.cpp
+++ b/tests/auto/blackbox/tst_blackbox.cpp
@@ -4971,6 +4971,40 @@ void TestBlackbox::propertiesInExportItems()
QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
}
+void TestBlackbox::protobuf_data()
+{
+ QTest::addColumn<QString>("projectFile");
+ QTest::addColumn<QStringList>("properties");
+ QTest::addColumn<bool>("successExpected");
+ QTest::newRow("cpp") << QString("addressbook_cpp.qbs") << QStringList() << true;
+ QTest::newRow("objc") << QString("addressbook_objc.qbs") << QStringList() << true;
+ QTest::newRow("import") << QString("import.qbs") << QStringList() << true;
+ QTest::newRow("missing import dir") << QString("needs-import-dir.qbs")
+ << QStringList() << false;
+ QTest::newRow("provided import dir")
+ << QString("needs-import-dir.qbs")
+ << QStringList("products.app.theImportDir:subdir") << true;
+}
+
+void TestBlackbox::protobuf()
+{
+ QDir::setCurrent(testDataDir + "/protobuf");
+ QFETCH(QString, projectFile);
+ QFETCH(QStringList, properties);
+ QFETCH(bool, successExpected);
+ rmDirR(relativeBuildDir());
+ QbsRunParameters resolveParams("resolve", QStringList{"-f", projectFile} << properties);
+ QCOMPARE(runQbs(resolveParams), 0);
+ const bool withProtobuf = m_qbsStdout.contains("has protobuf: true");
+ const bool withoutProtobuf = m_qbsStdout.contains("has protobuf: false");
+ QVERIFY2(withProtobuf || withoutProtobuf, m_qbsStdout.constData());
+ if (withoutProtobuf)
+ QSKIP("protobuf module not present");
+ QbsRunParameters runParams("run");
+ runParams.expectFailure = !successExpected;
+ QCOMPARE(runQbs(runParams) == 0, successExpected);
+}
+
void TestBlackbox::pseudoMultiplexing()
{
// This is "pseudo-multiplexing" on all platforms that initialize qbs.architectures
diff --git a/tests/auto/blackbox/tst_blackbox.h b/tests/auto/blackbox/tst_blackbox.h
index 3df507bdc..874690ad2 100644
--- a/tests/auto/blackbox/tst_blackbox.h
+++ b/tests/auto/blackbox/tst_blackbox.h
@@ -222,6 +222,8 @@ private slots:
void propertyPrecedence();
void properQuoting();
void propertiesInExportItems();
+ void protobuf_data();
+ void protobuf();
void pseudoMultiplexing();
void qbsConfig();
void qbsVersion();