Ver código fonte

Tune windows build procedure

- Update readme
- Remove deprecated variables set
- Add build all-in-one procedure with dependecies
- Make lookup of grpc and protobuf only in case if all-in-one build is not active
- Change grpc library linkage way
- Fix build issues related to component project update
- Add dll exports for public interfaces
Alexey Edelev 5 anos atrás
pai
commit
d4b0e93ab9

+ 3 - 0
.gitmodules

@@ -0,0 +1,3 @@
+[submodule "3rdparty/grpc"]
+	path = 3rdparty/grpc
+	url = https://github.com/grpc/grpc

+ 1 - 0
3rdparty/grpc

@@ -0,0 +1 @@
+Subproject commit 200e0fd4c0f18440c17626fb26ee5a7417ba9fe0

+ 15 - 14
CMakeLists.txt

@@ -16,8 +16,21 @@ if (Qt5Core_VERSION VERSION_LESS "5.11.4" OR (Qt5Core_VERSION VERSION_GREATER "5
     message(WARNING "Qt version<5.11.4 and (v5.12.0>=version<v5.12.3 has a bug in http2 connection handling. Tests using http2 feature and examples will not work!")
 endif()
 
-include("cmake/ProtobufLookup.cmake")
-include("cmake/gRPCLookup.cmake")
+if(EXISTS "${CMAKE_SOURCE_DIR}/3rdparty/grpc/CMakeLists.txt")
+    message(STATUS "Found local gRPC sources directory. Perform all-in-one build")
+    set(gRPC_BUILD_TESTS FALSE)
+    set(protobuf_BUILD_TESTS FALSE)
+    add_subdirectory("3rdparty/grpc")
+    if(TARGET grpc AND TARGET grpc++ AND TARGET grpc_cpp_plugin)
+        add_library(gRPC::grpc ALIAS grpc)
+        add_library(gRPC::grpc++ ALIAS grpc++)
+        add_executable(gRPC::grpc_cpp_plugin ALIAS grpc_cpp_plugin)
+        set(gRPC_FOUND TRUE)
+    endif()
+else()
+    include("cmake/ProtobufLookup.cmake")
+    include("cmake/gRPCLookup.cmake")
+endif()
 
 set(QTPROTOBUF_COMMON_NAMESPACE QtProtobufProject)
 set(GENERATOR_TARGET qtprotobufgen)
@@ -107,18 +120,6 @@ if(MAKE_TESTS)
         add_subdirectory(${GTest_SOURCE_DIR} ${GTest_BINARY_DIR})
     endif()
 
-    if(WIN32)
-        #Needs to set path to protobuf libraries
-        set(PROTOBUF_INSTALATION_PATH "")
-        set(Protobuf_PROTOC_EXECUTABLE ${PROTOBUF_INSTALATION_PATH}/bin/protoc.exe)
-        #Set  path to GTest build libraries
-        set(GTEST_BOTH_LIBRARIES "")
-
-        #Set path to GTest include directory
-        include_directories(${GTEST_INCLUDE_PATHS} "/")
-        link_directories(${GTEST_BOTH_LIBRARIES})
-    endif()
-
     enable_testing()
     add_subdirectory("tests")
 endif()

+ 42 - 4
README.md

@@ -1,21 +1,59 @@
-# qtprotobuf
+# QtProtobuf
 
 Protobuf plugin to generate Qt classes
 
 ## Linux Build
+### Prerequesties
+Check installation of protobuf and grpc in your system. Minimum required versions are protobuf-3.6.0 and grpc-1.15.0.
+
+**Note:** Older versions could be supported as well but not officially tested.
+
+#### All-in-one build
+If required versions of libraries are not found in your system, you may use all-in-one build procedure for prerequesties
+
+Clone grpc project from official repository to 3rdparty folder:
+
+```bash
+git submodule update --init --recursive
+```
+### Build
 ```bash
 mkdir build
 cd build
-cmake [-DCMAKE_PREFIX_PATH=<path/to/Qt5Config.cmake|path/to/qt5-config.cmake>] ..
-make -j<N>
+cmake ..
+cmake --build . -j <N> [--config <RELEASE|DEBUG>]
 ```
 
 ## Windows Build
+### Prerequesties
+
+Download and install:
+
+- Qt 5.12.3 or higher [1](https://download.qt.io/official_releases/qt/)
+- cmake-3.1 or higher [2](https://cmake.org/download/)
+- Strawberry perl 5.28 [3](http://strawberryperl.com/)
+- GoLang 1.10 or higher [4](https://golang.org/dl/)
+- Yasm 1.3 or higher [5](http://yasm.tortall.net/Download.html)
+- Actual Visual Studio Compiler with cmake support that required by Qt [6](https://visualstudio.microsoft.com/downloads/)
+
+**Note:** All applications should be in PATH
+
+Clone grpc project from official repository to 3rdparty folder:
+
+```bash
+git submodule update --init --recursive
+```
+
+### Build
+Open Qt MSVC command line and follow steps:
+
 ```bash
+"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" amd64
+cd <directory with qtprotobuf project>
 mkdir build
 cd build
 cmake ..
-cmake --build . --target qtprotobuf --config RELEASE
+cmake --build . -j <N> [--config <RELEASE|DEBUG>]
 ```
 
 ## Usage

+ 36 - 40
cmake/ProtobufLookup.cmake

@@ -1,47 +1,43 @@
+find_package(Protobuf CONFIG)
 if(NOT Protobuf_FOUND)
-    find_package(Protobuf CONFIG)
-    if(NOT Protobuf_FOUND)
-        if(CMAKE_SIZEOF_VOID_P EQUAL 8)
-            set(FIND_LIBRARY_USE_LIB64_PATHS TRUE)
-            set(FIND_LIBRARY_USE_LIBX32_PATHS FALSE)
-            set(FIND_LIBRARY_USE_LIB32_PATHS FALSE)
-        else()
-            set(FIND_LIBRARY_USE_LIBX32_PATHS TRUE)
-            set(FIND_LIBRARY_USE_LIB32_PATHS TRUE)
-            set(FIND_LIBRARY_USE_LIB64_PATHS FALSE)
-        endif()
+    if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+        set(FIND_LIBRARY_USE_LIB64_PATHS TRUE)
+        set(FIND_LIBRARY_USE_LIBX32_PATHS FALSE)
+        set(FIND_LIBRARY_USE_LIB32_PATHS FALSE)
+    else()
+        set(FIND_LIBRARY_USE_LIBX32_PATHS TRUE)
+        set(FIND_LIBRARY_USE_LIB32_PATHS TRUE)
+        set(FIND_LIBRARY_USE_LIB64_PATHS FALSE)
+    endif()
 
-        find_library(Protobuf_LIBRARY protobuf)
-        if(NOT Protobuf_LIBRARY STREQUAL PROTOBUF_LIBRARY-NOTFOUND)
-            add_library(protobuf::libprotobuf SHARED IMPORTED)
-            set_target_properties(protobuf::libprotobuf PROPERTIES IMPORTED_LOCATION ${Protobuf_LIBRARY})
-        endif()
+    find_library(Protobuf_LIBRARY protobuf)
+    if(NOT TARGET protobuf::libprotobuf AND NOT Protobuf_LIBRARY STREQUAL PROTOBUF_LIBRARY-NOTFOUND)
+        add_library(protobuf::libprotobuf SHARED IMPORTED)
+        set_target_properties(protobuf::libprotobuf PROPERTIES IMPORTED_LOCATION ${Protobuf_LIBRARY})
+    endif()
 
-        find_program(Protobuf_PROTOC_EXECUTABLE protoc)
-        if(NOT Protobuf_PROTOC_EXECUTABLE STREQUAL Protobuf_PROTOC_EXECUTABLE-NOTFOUND)
-            add_executable(protobuf::protoc IMPORTED)
-            set_target_properties(protobuf::protoc PROPERTIES IMPORTED_LOCATION ${Protobuf_PROTOC_EXECUTABLE})
-        endif()
+    find_program(Protobuf_PROTOC_EXECUTABLE protoc)
+    if(NOT TARGET protobuf::protoc AND NOT Protobuf_PROTOC_EXECUTABLE STREQUAL Protobuf_PROTOC_EXECUTABLE-NOTFOUND)
+        add_executable(protobuf::protoc IMPORTED)
+        set_target_properties(protobuf::protoc PROPERTIES IMPORTED_LOCATION ${Protobuf_PROTOC_EXECUTABLE})
+    endif()
 
-        find_package(Threads)
-        find_library(Protobuf_PROTOC_LIBRARY protoc)
-        if(NOT Protobuf_PROTOC_LIBRARY STREQUAL PROTOBUF_PROTOC_LIBRARY-NOTFOUND)
-            add_library(protobuf::libprotoc SHARED IMPORTED)
-            set_target_properties(protobuf::libprotoc PROPERTIES IMPORTED_LOCATION ${Protobuf_PROTOC_LIBRARY}
-                INTERFACE_LINK_LIBRARIES Threads::Threads)
-        endif()
+    find_package(Threads)
+    find_library(Protobuf_PROTOC_LIBRARY protoc)
+    if(NOT TARGET protobuf::libprotoc AND NOT Protobuf_PROTOC_LIBRARY STREQUAL PROTOBUF_PROTOC_LIBRARY-NOTFOUND)
+        add_library(protobuf::libprotoc SHARED IMPORTED)
+        set_target_properties(protobuf::libprotoc PROPERTIES IMPORTED_LOCATION ${Protobuf_PROTOC_LIBRARY}
+            INTERFACE_LINK_LIBRARIES Threads::Threads)
+    endif()
 
-        unset(Protobuf_FOUND)
-        if(NOT Protobuf_LIBRARY STREQUAL Protobuf_LIBRARY-NOTFOUND
-                AND NOT Protobuf_PROTOC_EXECUTABLE STREQUAL Protobuf_PROTOC_EXECUTABLE-NOTFOUND
-                AND NOT Protobuf_PROTOC_LIBRARY STREQUAL Protobuf_PROTOC_LIBRARY-NOTFOUND)
-            set(Protobuf_FOUND TRUE)
-            message(STATUS "Found protobuf installation: ${Protobuf_PROTOC_EXECUTABLE} ${Protobuf_PROTOC_LIBRARY} ${Protobuf_LIBRARY}")
-        else()
-            message(FATAL_ERROR "Protobuf is a hard dependency of the project. You may install it (with gRPC) by following instructions in cmake/gRPCBuild.cmake script.")
-            unset(Protobuf_LIBRARY)
-            unset(Protobuf_PROTOC_EXECUTABLE)
-            unset(Protobuf_PROTOC_LIBRARY)
-        endif()
+    unset(Protobuf_FOUND)
+    if(TARGET protobuf::libprotoc AND TARGET protobuf::protoc AND TARGET protobuf::libprotobuf)
+        set(Protobuf_FOUND TRUE)
+        message(STATUS "Found protobuf installation: ${Protobuf_PROTOC_EXECUTABLE} ${Protobuf_PROTOC_LIBRARY} ${Protobuf_LIBRARY}")
+    else()
+        message(FATAL_ERROR "Protobuf is a hard dependency of the project. You may install it (with gRPC) by following instructions in cmake/gRPCBuild.cmake script.")
+        unset(Protobuf_LIBRARY)
+        unset(Protobuf_PROTOC_EXECUTABLE)
+        unset(Protobuf_PROTOC_LIBRARY)
     endif()
 endif()

+ 33 - 36
cmake/gRPCLookup.cmake

@@ -1,43 +1,40 @@
+find_package(gRPC CONFIG)
 if(NOT gRPC_FOUND)
-    find_package(gRPC CONFIG)
-    if(NOT gRPC_FOUND)
-        if(CMAKE_SIZEOF_VOID_P EQUAL 8)
-            set(FIND_LIBRARY_USE_LIB64_PATHS TRUE)
-            set(FIND_LIBRARY_USE_LIBX32_PATHS FALSE)
-            set(FIND_LIBRARY_USE_LIB32_PATHS FALSE)
-        else()
-            set(FIND_LIBRARY_USE_LIBX32_PATHS TRUE)
-            set(FIND_LIBRARY_USE_LIB32_PATHS TRUE)
-            set(FIND_LIBRARY_USE_LIB64_PATHS FALSE)
-        endif()
+    if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+        set(FIND_LIBRARY_USE_LIB64_PATHS TRUE)
+        set(FIND_LIBRARY_USE_LIBX32_PATHS FALSE)
+        set(FIND_LIBRARY_USE_LIB32_PATHS FALSE)
+    else()
+        set(FIND_LIBRARY_USE_LIBX32_PATHS TRUE)
+        set(FIND_LIBRARY_USE_LIB32_PATHS TRUE)
+        set(FIND_LIBRARY_USE_LIB64_PATHS FALSE)
+    endif()
 
-        find_program(gRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin)
-        if(NOT gRPC_CPP_PLUGIN_EXECUTABLE STREQUAL gRPC_CPP_PLUGIN_EXECUTABLE-NOTFOUND)
-            add_executable(gRPC::grpc_cpp_plugin IMPORTED)
-            set_target_properties(gRPC::grpc_cpp_plugin PROPERTIES IMPORTED_LOCATION ${gRPC_CPP_PLUGIN_EXECUTABLE})
-        endif()
+    find_program(gRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin)
+    if(NOT TARGET gRPC::grpc_cpp_plugin AND NOT gRPC_CPP_PLUGIN_EXECUTABLE STREQUAL gRPC_CPP_PLUGIN_EXECUTABLE-NOTFOUND)
+        add_executable(gRPC::grpc_cpp_plugin IMPORTED)
+        set_target_properties(gRPC::grpc_cpp_plugin PROPERTIES IMPORTED_LOCATION ${gRPC_CPP_PLUGIN_EXECUTABLE})
+    endif()
 
-        find_library(gRPC_LIBRARY grpc)
-        if(NOT gRPC_LIBRARY STREQUAL gRPC_LIBRARY-NOTFOUND)
-            add_library(gRPC::grpc SHARED IMPORTED)
-            set_target_properties(gRPC::grpc PROPERTIES IMPORTED_LOCATION ${gRPC_LIBRARY})
-        endif()
+    find_library(gRPC_LIBRARY grpc)
+    if(NOT TARGET gRPC::grpc AND NOT gRPC_LIBRARY STREQUAL gRPC_LIBRARY-NOTFOUND)
+        add_library(gRPC::grpc SHARED IMPORTED)
+        set_target_properties(gRPC::grpc PROPERTIES IMPORTED_LOCATION ${gRPC_LIBRARY})
+    endif()
 
-        find_library(gRPC_CPP_LIBRARY grpc++)
-        if(NOT gRPC_CPP_LIBRARY STREQUAL gRPC_LIBRARY-NOTFOUND)
-            add_library(gRPC::grpc++ SHARED IMPORTED)
-            set_target_properties(gRPC::grpc++ PROPERTIES IMPORTED_LOCATION ${gRPC_CPP_LIBRARY} INTERFACE_LINK_LIBRARIES protobuf::libprotobuf)
-        endif()
+    find_library(gRPC_CPP_LIBRARY grpc++)
+    if(NOT TARGET gRPC::grpc++ AND NOT gRPC_CPP_LIBRARY STREQUAL gRPC_LIBRARY-NOTFOUND)
+        add_library(gRPC::grpc++ SHARED IMPORTED)
+        set_target_properties(gRPC::grpc++ PROPERTIES IMPORTED_LOCATION ${gRPC_CPP_LIBRARY} INTERFACE_LINK_LIBRARIES protobuf::libprotobuf)
+    endif()
 
-        unset(gRPC_FOUND)
-        if(NOT gRPC_LIBRARY STREQUAL gRPC_LIBRARY-NOTFOUND
-                AND NOT gRPC_CPP_PLUGIN_EXECUTABLE STREQUAL gRPC_CPP_PLUGIN_EXECUTABLE-NOTFOUND
-                AND NOT gRPC_CPP_LIBRARY STREQUAL gRPC_LIBRARY-NOTFOUND)
-            set(gRPC_FOUND TRUE)
-        else()
-            unset(gRPC_LIBRARY)
-            unset(gRPC_CPP_PLUGIN_EXECUTABLE)
-            unset(gRPC_CPP_LIBRARY)
-        endif()
+    unset(gRPC_FOUND)
+    if(TARGET gRPC::grpc++ AND TARGET gRPC::grpc AND TARGET gRPC::grpc_cpp_plugin)
+        message(STATUS "Found gRPC")
+        set(gRPC_FOUND TRUE)
+    else()
+        unset(gRPC_LIBRARY)
+        unset(gRPC_CPP_PLUGIN_EXECUTABLE)
+        unset(gRPC_CPP_LIBRARY)
     endif()
 endif()

+ 0 - 8
examples/addressbookserver/CMakeLists.txt

@@ -15,13 +15,5 @@ protobuf_generate_all(TARGET ${TARGET}
     GENERATED_SOURCES ${GENERATED_SOURCES}
     PROTO_FILES ${PROTO_FILES})
 
-if(WIN32)
-    include_directories(${GRPC_INCLUDE_PATHS} "/")
-    set(GRPC_LIBRARIES "")
-    #Needs to set path to protobuf libraries
-    set(PROTOBUF_LIBRARIES_PATH ${PROTOBUF_INSTALATION_PATH}/lib)
-    link_directories(${PROTOBUF_LIBRARIES_PATH} ${GRPC_LIBRARIES})
-endif()
-
 target_link_libraries(${TARGET} protobuf::libprotobuf gRPC::grpc++ gRPC::grpc)
 file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/cert.pem ${CMAKE_CURRENT_SOURCE_DIR}/key.pem DESTINATION ${CMAKE_CURRENT_BINARY_DIR})

+ 0 - 8
examples/simplechatserver/CMakeLists.txt

@@ -15,13 +15,5 @@ protobuf_generate_all(TARGET ${TARGET}
     GENERATED_SOURCES ${GENERATED_SOURCES}
     PROTO_FILES ${PROTO_FILES})
 
-if(WIN32)
-    include_directories(${GRPC_INCLUDE_PATHS} "/")
-    set(GRPC_LIBRARIES "")
-    #Needs to set path to protobuf libraries
-    set(PROTOBUF_LIBRARIES_PATH ${PROTOBUF_INSTALATION_PATH}/lib)
-    link_directories(${PROTOBUF_LIBRARIES_PATH} ${GRPC_LIBRARIES})
-endif()
-
 target_link_libraries(${TARGET} protobuf::libprotobuf gRPC::grpc++ gRPC::grpc)
 file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/cert.pem ${CMAKE_CURRENT_SOURCE_DIR}/key.pem DESTINATION ${CMAKE_CURRENT_BINARY_DIR})

+ 8 - 2
src/grpc/CMakeLists.txt

@@ -24,13 +24,16 @@ file(GLOB HEADERS asyncreply.h
     abstractclient.h
     abstractcredentials.h
     sslcredentials.h
-    insecurecredentials.h)
+    insecurecredentials.h
+    qtgrpc_global.h)
 
 add_library(${TARGET} SHARED ${SOURCES})
+target_compile_definitions(${TARGET} PRIVATE QTGRPC_LIB)
+
 add_library(${QTPROTOBUF_COMMON_NAMESPACE}::${TARGET} ALIAS ${TARGET})
 set_target_properties(${TARGET} PROPERTIES VERSION ${PROJECT_VERSION} PUBLIC_HEADER "${HEADERS}" OUTPUT_NAME ${TARGET})
 target_include_directories(${TARGET} PUBLIC 
-    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> 
+    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
     $<INSTALL_INTERFACE:${TARGET_INCLUDE_DIR}>
 )
 target_link_libraries(${TARGET} PUBLIC ${QTPROTOBUF_COMMON_NAMESPACE}::QtProtobuf Qt5::Core Qt5::Network)
@@ -58,3 +61,6 @@ configure_package_config_file(
 install(FILES "${CMAKE_BINARY_DIR}/${TARGET_CONFIG}.cmake" DESTINATION "${TARGET_CMAKE_DIR}")
 
 export(TARGETS ${TARGET} NAMESPACE ${QTPROTOBUF_COMMON_NAMESPACE}:: FILE ${TARGET_EXPORT}.cmake)
+
+configure_file("${CMAKE_SOURCE_DIR}/cmake/gRPCLookup.cmake" "${CMAKE_BINARY_DIR}/gRPCLookup.cmake" COPYONLY)
+install(FILES "${CMAKE_BINARY_DIR}/gRPCLookup.cmake" DESTINATION "${TARGET_CMAKE_DIR}")

+ 2 - 0
src/grpc/QtGrpcConfig.cmake.in

@@ -1,3 +1,5 @@
+include("${CMAKE_CURRENT_LIST_DIR}/gRPCLookup.cmake")
+
 include(CMakeFindDependencyMacro)
 
 find_dependency(QtProtobufProject COMPONENTS QtProtobuf REQUIRED CONFIG)

+ 3 - 1
src/grpc/abstractchannel.h

@@ -29,12 +29,14 @@
 #include <QByteArray>
 #include <functional>
 
+#include "qtgrpc_global.h"
+
 namespace qtprotobuf {
 
 class AsyncReply;
 class AbstractClient;
 
-class AbstractChannel
+class QTGRPCSHARED_EXPORT AbstractChannel
 {
 public:
     /*!

+ 3 - 1
src/grpc/abstractclient.h

@@ -37,12 +37,14 @@
 #include "abstractchannel.h"
 #include "asyncreply.h"
 
+#include "qtgrpc_global.h"
+
 namespace qtprotobuf {
 
 class AbstractChannel;
 class AbstractClientPrivate;
 
-class AbstractClient : public QObject
+class QTGRPCSHARED_EXPORT AbstractClient : public QObject
 {
 public:
     void attachChannel(std::shared_ptr<AbstractChannel> channel);

+ 5 - 3
src/grpc/abstractcredentials.h

@@ -31,12 +31,14 @@
 
 #include <functional>
 
+#include "qtgrpc_global.h"
+
 namespace qtprotobuf {
 
 class CallCredentials;
 class ChannelCredentials;
 
-class AbstractCredentials
+class QTGRPCSHARED_EXPORT AbstractCredentials
 {
 public:
     template<typename Call, typename Channel,
@@ -71,7 +73,7 @@ private:
     CredentialMap mChannelCredentials;
 };
 
-class CallCredentials : public AbstractCredentials
+class QTGRPCSHARED_EXPORT CallCredentials : public AbstractCredentials
 {
 protected:
     CallCredentials(const CredentialMap& credentialMap) {
@@ -83,7 +85,7 @@ private:
     CallCredentials() = default;
 };
 
-class ChannelCredentials : public AbstractCredentials
+class QTGRPCSHARED_EXPORT ChannelCredentials : public AbstractCredentials
 {
 protected:
     ChannelCredentials(const CredentialMap& credentialMap) {

+ 3 - 1
src/grpc/asyncreply.h

@@ -32,9 +32,11 @@
 
 #include "abstractchannel.h"
 
+#include "qtgrpc_global.h"
+
 namespace qtprotobuf {
 
-class AsyncReply final : public QObject
+class QTGRPCSHARED_EXPORT AsyncReply final : public QObject
 {
     Q_OBJECT
 public:

+ 3 - 1
src/grpc/http2channel.h

@@ -30,12 +30,14 @@
 #include <QString>
 #include <QByteArray>
 
+#include "qtgrpc_global.h"
+
 namespace qtprotobuf {
 
 struct Http2ChannelPrivate;
 class AbstractCredentials;
 
-class Http2Channel final : public AbstractChannel
+class QTGRPCSHARED_EXPORT Http2Channel final : public AbstractChannel
 {
 public:
     Http2Channel(const QString &addr, quint16 port, const AbstractCredentials &credentials);

+ 3 - 1
src/grpc/insecurecredentials.h

@@ -27,9 +27,11 @@
 
 #include "abstractcredentials.h"
 
+#include "qtgrpc_global.h"
+
 namespace qtprotobuf {
 
-class InsecureCredentials : public ChannelCredentials
+class QTGRPCSHARED_EXPORT InsecureCredentials : public ChannelCredentials
 {
 public:
     InsecureCredentials() : ChannelCredentials(CredentialMap()) {}

+ 34 - 0
src/grpc/qtgrpc_global.h

@@ -0,0 +1,34 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2019 Alexey Edelev <semlanik@gmail.com>
+ *
+ * This file is part of qtprotobuf project https://git.semlanik.org/semlanik/qtprotobuf
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ * software and associated documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software, and
+ * to permit persons to whom the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies
+ * or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#pragma once
+
+#include <QtCore/QtGlobal>
+
+#ifdef QTGRPC_LIB
+    #define QTGRPCSHARED_EXPORT Q_DECL_EXPORT
+#else
+    #define QTGRPCSHARED_EXPORT Q_DECL_IMPORT
+#endif

+ 3 - 1
src/grpc/sslcredentials.h

@@ -29,9 +29,11 @@
 
 #include <QSslConfiguration>
 
+#include "qtgrpc_global.h"
+
 namespace qtprotobuf {
 
-class SslCredentials : public ChannelCredentials
+class QTGRPCSHARED_EXPORT SslCredentials : public ChannelCredentials
 {
 public:
     SslCredentials(const QSslConfiguration &configuation) :

+ 4 - 1
src/protobuf/CMakeLists.txt

@@ -23,9 +23,12 @@ file(GLOB HEADERS
     qtprotobuftypes.h
     qtprotobuf.h
     selfcheckiterator.h
-    qtprotobuflogging.h)
+    qtprotobuflogging.h
+    qtprotobuf_global.h)
 
 add_library(${TARGET} SHARED ${SOURCES})
+target_compile_definitions(${TARGET} PRIVATE QTPROTOBUF_LIB)
+
 add_library(${QTPROTOBUF_COMMON_NAMESPACE}::${TARGET} ALIAS ${TARGET})
 set_target_properties(${TARGET} PROPERTIES VERSION ${PROJECT_VERSION} PUBLIC_HEADER "${HEADERS}" OUTPUT_NAME ${TARGET})
 target_include_directories(${TARGET} PUBLIC 

+ 3 - 1
src/protobuf/qprotobufobject_p.h

@@ -40,6 +40,8 @@
 #include "qtprotobuflogging.h"
 #include "selfcheckiterator.h"
 
+#include "qtprotobuf_global.h"
+
 #define ASSERT_FIELD_NUMBER(X) Q_ASSERT_X(X < 536870912 && X > 0, T::staticMetaObject.className(), "fieldIndex is out of range")
 
 namespace qtprotobuf {
@@ -53,7 +55,7 @@ struct make_unsigned<int32> { typedef typename std::make_unsigned<decltype(int32
 template<>
 struct make_unsigned<int64> { typedef typename std::make_unsigned<decltype(int64::_t)>::type type; };
 
-class ProtobufObjectPrivate
+class QTPROTOBUFSHARED_EXPORT ProtobufObjectPrivate
 {
     ProtobufObjectPrivate() = delete;
     ~ProtobufObjectPrivate() = delete;

+ 1 - 1
src/protobuf/qtprotobuf.h

@@ -34,7 +34,7 @@
 
 namespace qtprotobuf {
 
-class QtProtobuf {
+class QTPROTOBUFSHARED_EXPORT QtProtobuf {
 public:
     static void init() {
         static bool registationDone = false;

+ 34 - 0
src/protobuf/qtprotobuf_global.h

@@ -0,0 +1,34 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2019 Alexey Edelev <semlanik@gmail.com>
+ *
+ * This file is part of qtprotobuf project https://git.semlanik.org/semlanik/qtprotobuf
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ * software and associated documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software, and
+ * to permit persons to whom the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies
+ * or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#pragma once
+
+#include <QtCore/QtGlobal>
+
+#ifdef QTPROTOBUF_LIB
+    #define QTPROTOBUFSHARED_EXPORT Q_DECL_EXPORT
+#else
+    #define QTPROTOBUFSHARED_EXPORT Q_DECL_IMPORT
+#endif

+ 4 - 1
src/protobuf/selfcheckiterator.h

@@ -26,11 +26,14 @@
 #include <QByteArray>
 #include <stdexcept>
 
+#include "qtprotobuf_global.h"
+
 #pragma once
 
 namespace qtprotobuf {
 
-class SelfcheckIterator {
+class QTPROTOBUFSHARED_EXPORT SelfcheckIterator
+{
 public:
     SelfcheckIterator(const QByteArray& container) : m_sizeLeft(container.size())
       , m_containerSize(container.size())