Browse Source

Add static linking for quick plugin

- Enable static build for QtProtobuf Quick plugin
- Add extra macro to enable staticaly linked protobuf plugin
- Remove deprecated static target names
- Fix cmake generator warnings related to automoc
- Add automoc uri option for quick plugin
- Add microjson dependency for static QtProtobuf
- Add documentation about QtProtobuf usage in QML

Fixes: #119
Alexey Edelev 4 years ago
parent
commit
37fce9d13c

+ 1 - 0
CMakeLists.txt

@@ -46,6 +46,7 @@ endif()
 
 set(gtest_force_shared_crt OFF)
 set(GENERATOR_TARGET qtprotobufgen)
+set(PROTOBUF_QUICK_PLUGIN_NAME protobufquickplugin)
 set(QT_PROTOBUF_EXECUTABLE_INSTALL ${CMAKE_INSTALL_FULL_BINDIR}/${GENERATOR_TARGET})
 set(QT_PROTOBUF_EXECUTABLE $<TARGET_FILE:${GENERATOR_TARGET}> CACHE STRING "QT_PROTOBUF_EXECUTABLE is set ${QT_PROTOBUF_EXECUTABLE}" FORCE)
 

+ 2 - 0
cmake/QtProtobufGen.cmake

@@ -112,6 +112,8 @@ function(qtprotobuf_generate)
             list(APPEND GENERATED_HEADERS_FULL ${OUT_DIR}/${GENERATED_BASENAME}.h)
         endif()
         set_property(SOURCE ${OUT_DIR}/${GENERATED_DIRECTORY}/${GENERATED_BASENAME}.cpp PROPERTY SKIP_AUTOMOC ON)
+        set_property(SOURCE ${OUT_DIR}/${GENERATED_DIRECTORY}/${GENERATED_BASENAME}.cpp PROPERTY SKIP_AUTOUIC ON)
+        set_property(SOURCE ${OUT_DIR}/${GENERATED_DIRECTORY}/${GENERATED_BASENAME}.cpp PROPERTY SKIP_AUTOGEN ON)
     endforeach()
 
     set_source_files_properties(${GENERATED_SOURCES_FULL} PROPERTIES GENERATED TRUE)

+ 1 - 1
src/generator/main.cpp

@@ -38,11 +38,11 @@
  * QtProtobuf distributed in terms of MIT license and is free for modification and use under MIT
  * license <a href="https://github.com/semlanik/qtprotobuf/blob/master/LICENSE">terms</a>.
  *
- * QtProtobuf has 4 modules:
  *  - \ref generator
  *  - \ref QtProtobuf
  *  - \ref QtGrpc
  *  - \ref QtProtobufWellKnownTypes
+ *  - \ref QtProtobufQuick
  *
  * \subsection gettingstarted Getting Started with QtProtobuf
  *

+ 0 - 1
src/grpc/CMakeLists.txt

@@ -1,5 +1,4 @@
 set(TARGET QtGrpc)
-set(TARGET_STATIC ${TARGET}Static)
 set(TARGET_EXPORT ${TARGET}Targets)
 set(TARGET_CONFIG ${TARGET}Config)
 

+ 0 - 1
src/protobuf/CMakeLists.txt

@@ -1,5 +1,4 @@
 set(TARGET QtProtobuf)
-set(TARGET_STATIC ${TARGET}Static)
 set(TARGET_EXPORT ${TARGET}Targets)
 set(TARGET_CONFIG ${TARGET}Config)
 

+ 11 - 1
src/protobuf/QtProtobufConfig.cmake.in

@@ -1,15 +1,25 @@
 include("${CMAKE_CURRENT_LIST_DIR}/ProtobufLookup.cmake")
 
+set(QT_PROTOBUF_STATIC @QT_PROTOBUF_STATIC@)
+
+if(QT_PROTOBUF_STATIC)
+    include(CMakeFindDependencyMacro)
+    find_dependency(microjson REQUIRED CONFIG)
+endif()
+
 if(NOT TARGET @TARGET@ AND NOT @TARGET@_BINARY_DIR)
     include("${CMAKE_CURRENT_LIST_DIR}/@TARGET_EXPORT@.cmake")
 endif()
 
+if(QT_PROTOBUF_STATIC AND NOT TARGET @PROTOBUF_QUICK_PLUGIN_NAME@ AND NOT @PROTOBUF_QUICK_PLUGIN_NAME@_BINARY_DIR)
+    include("${CMAKE_CURRENT_LIST_DIR}/@PROTOBUF_QUICK_PLUGIN_NAME@Targets.cmake")
+endif()
+
 @PACKAGE_INIT@
 set(PROTO_PARSER "${CMAKE_CURRENT_LIST_DIR}/parsemessages.go")
 set(GENERATOR_TARGET "@GENERATOR_TARGET@")
 set(QT_PROTOBUF_PROJECT "@QT_PROTOBUF_PROJECT@")
 set(QT_PROTOBUF_EXECUTABLE_INSTALL "@QT_PROTOBUF_EXECUTABLE_INSTALL@")
-set(QT_PROTOBUF_STATIC @QT_PROTOBUF_STATIC@)
 
 if(QT_PROTOBUF_STATIC)
     add_definitions(-DQT_PROTOBUF_STATIC)#Old cmake versions compatibility

+ 39 - 0
src/protobuf/qtprotobufglobal.h

@@ -50,3 +50,42 @@
         Q_DISABLE_COPY(Class) \
         Q_DISABLE_MOVE(Class)
 #endif
+/*!
+ * \ingroup QtProtobuf
+ * \def Q_PROTOBUF_IMPORT_QUICK_PLUGIN()
+ *      Imports statically linked QtProtobufQuickPlugin.<br/>
+ *      If you use statically linked QtProtobuf, you need to call
+ *      Q_PROTOBUF_IMPORT_QUICK_PLUGIN macro before use QtProtobuf in QML.<br/>
+ * C++:
+ * \code
+ * int main(int argc, char *argv[]) {
+ *     ...
+ *     QtProtobuf::qRegisterProtobufTypes();
+ *     Q_PROTOBUF_IMPORT_QUICK_PLUGIN()
+ *     ...
+ * }
+ * \endcode
+ *
+ * QML:
+ * \code
+ * //Make QtProtobuf types visible in QML
+ * import QtProtobuf 0.4 //Use recent QtProtobuf version
+ * ...
+ * Item {
+ *     //QtProtobuf usage
+ * }
+ * ...
+ * \endcode
+ */
+#ifndef Q_PROTOBUF_IMPORT_QUICK_PLUGIN
+    #ifdef QT_PROTOBUF_STATIC
+        #include <QtPlugin>
+        #include <QQmlExtensionPlugin>
+        #define Q_PROTOBUF_IMPORT_QUICK_PLUGIN() \
+            Q_IMPORT_PLUGIN(QtProtobufQuickPlugin) \
+            qobject_cast<QQmlExtensionPlugin*>(qt_static_plugin_QtProtobufQuickPlugin().instance())->registerTypes("QtProtobuf");
+    #else
+        #define Q_PROTOBUF_IMPORT_QUICK_PLUGIN()
+    #endif //QT_PROTOBUF_STATIC
+#endif //Q_PROTOBUF_IMPORT_QUICK_PLUGIN
+

+ 37 - 8
src/protobuf/quick/CMakeLists.txt

@@ -1,12 +1,15 @@
-set(TARGET protobufquickplugin)
+set(TARGET ${PROTOBUF_QUICK_PLUGIN_NAME})
 
+set(TARGET_EXPORT ${TARGET}Targets)
 set(TARGET_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR}/${TARGET})
+set(TARGET_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
+
+find_package(Qt5 COMPONENTS Core Qml REQUIRED)
 
 set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTOMOC_MOC_OPTIONS -Muri=QtProtobuf)
 set(CMAKE_AUTORCC ON)
 
-find_package(Qt5 COMPONENTS Core Qml REQUIRED)
-
 include(${QT_PROTOBUF_CMAKE_DIR}/QtProtobufCommon.cmake)
 
 extract_qt_variable(QT_INSTALL_QML)
@@ -20,7 +23,17 @@ file(GLOB HEADERS
     qtprotobufquickplugin.h
     qtprotobufquick_global.h)
 
-add_library(${TARGET} SHARED ${SOURCES})
+if(QT_PROTOBUF_STATIC)
+    if(WIN32)
+        message(WARNING "Static version of QtProtobuf is not fully tested on Win32 platforms")
+    endif()
+    add_library(${TARGET} STATIC ${SOURCES})
+    target_compile_definitions(${TARGET} PRIVATE QT_PROTOBUF_STATIC QT_STATICPLUGIN PUBLIC QT_PROTOBUF_QUICK_PLUGIN_NAME="QtProtobufQuickPlugin")
+    set(QT_PROTOBUF_EXTRA_COMPILE_DIFINITIONS QT_PROTOBUF_STATIC)
+else()
+    add_library(${TARGET} SHARED ${SOURCES})
+endif()
+
 target_link_libraries(${TARGET} PRIVATE Qt5::Core Qt5::Qml ${QT_PROTOBUF_PROJECT}::QtProtobuf)
 set_target_properties(${TARGET} PROPERTIES
     LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/QtProtobuf"
@@ -42,13 +55,29 @@ foreach(QML_PRIVATE_HEADER IN LISTS Qt5Qml_PRIVATE_INCLUDE_DIRS)
 endforeach()
 
 target_include_directories(${TARGET} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../ ${Qt5Qml_PRIVATE_INCLUDE_DIRS})
-install(TARGETS ${TARGET} COMPONENT lib
-    PUBLIC_HEADER DESTINATION "${TARGET_INCLUDE_DIR}" COMPONENT dev
-    RUNTIME DESTINATION "${TARGET_IMPORTS_DIR}" COMPONENT lib
-    LIBRARY DESTINATION "${TARGET_IMPORTS_DIR}" COMPONENT lib)
+
+if(QT_PROTOBUF_STATIC)
+    add_library(${QT_PROTOBUF_PROJECT}::${TARGET} ALIAS ${TARGET})
+    install(TARGETS ${TARGET} COMPONENT lib
+        EXPORT ${TARGET_EXPORT} COMPONENT dev
+        ARCHIVE DESTINATION "${TARGET_IMPORTS_DIR}" COMPONENT lib
+        RUNTIME DESTINATION "${TARGET_IMPORTS_DIR}" COMPONENT lib
+        LIBRARY DESTINATION "${TARGET_IMPORTS_DIR}" COMPONENT lib)
+    install(EXPORT ${TARGET_EXPORT} NAMESPACE ${QT_PROTOBUF_PROJECT}:: FILE ${TARGET_EXPORT}.cmake DESTINATION ${TARGET_CMAKE_DIR} COMPONENT dev)
+else()
+    install(TARGETS ${TARGET} COMPONENT lib
+        ARCHIVE DESTINATION "${TARGET_IMPORTS_DIR}" COMPONENT lib
+        RUNTIME DESTINATION "${TARGET_IMPORTS_DIR}" COMPONENT lib
+        LIBRARY DESTINATION "${TARGET_IMPORTS_DIR}" COMPONENT lib)
+endif()
+
 
 add_custom_command(TARGET ${TARGET}
     COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/qmldir $<TARGET_FILE_DIR:${TARGET}>/qmldir
     COMMENT "Copying qmldir to binary directory")
 
 install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/qmldir DESTINATION "${TARGET_IMPORTS_DIR}" COMPONENT lib)
+
+if(QT_PROTOBUF_STATIC)
+    export(TARGETS ${TARGET} NAMESPACE ${QT_PROTOBUF_PROJECT}:: FILE ${TARGET_EXPORT}.cmake)
+endif()

+ 1 - 0
src/protobuf/quick/qtprotobufquickplugin.cpp

@@ -37,6 +37,7 @@ static QVariant coverter(const QString &str) {
 
 void QtProtobufQuickPlugin::registerTypes(const char *uri)
 {
+    // @uri QtProtobuf
     Q_ASSERT(uri == QLatin1String("QtProtobuf"));
     qmlRegisterModule(uri, QT_PROTOBUF_VERSION_MAJOR, QT_PROTOBUF_VERSION_MINOR);
     QQmlMetaType::registerCustomStringConverter(qMetaTypeId<QtProtobuf::int32>(), coverter<QtProtobuf::int32>);

+ 53 - 0
src/protobuf/quick/qtprotobufquickplugin.h

@@ -28,6 +28,59 @@
 #include <QQmlExtensionPlugin>
 #include "qtprotobufquick_global.h"
 
+/*!
+ * \defgroup QtProtobufQuick
+ * \details
+ * QtProtobuf allows to use generated classes in QML. All types are registred automatically when QtProtobuf::qRegisterProtobufTypes() called.
+ * To make generated classes and QtProtobuf types visible in QML you need to import QtProtobuf QML plugin and your protobuf package
+ *
+ * sample.proto:
+ * \code
+ * syntax = "proto3";
+ * package qtprotobuf.sample;
+ * message SampleMessage {
+ *     int32 sampleField = 1;
+ * }
+ * \endcode
+ *
+ * QML:
+ * \code
+ * //Enable QtProtobuf types
+ * import QtProtobuf 0.4 //Use recent QtProtobuf version
+ * //Import types from sample.proto
+ * import qtprotobuf.sample 1.0
+ *
+ * Item {
+ * ...
+ *     SampleMessage {
+ *         sampleField: 10
+ *     }
+ * ...
+ * }
+ * \endcode
+ *
+ * \section qtprotobufquick_static Static QtProtobuf with QML
+ * For statically built QtProtobuf it's neccssary to link `protobufquickplugin` target manually:
+ * CMakeLists.txt:
+ * \code
+ * ...
+ * if(QT_PROTOBUF_STATIC)
+ *     target_link_libraries(${TARGET} PRIVATE QtProtobufProject::protobufquickplugin)
+ * endif()
+ * ...
+ * \endcode
+ *
+ * To make QtProtobuf QML plugin visible in QML, call Q_PROTOBUF_IMPORT_QUICK_PLUGIN() macro:
+ * \code
+ * int main(int argc, char *argv[]) {
+ *     ...
+ *     QtProtobuf::qRegisterProtobufTypes();
+ *     Q_PROTOBUF_IMPORT_QUICK_PLUGIN()
+ *     ...
+ * }
+ * \endcode
+ */
+
 /*!
  * \private
  * \brief The QtProtobufQuickPlugin class

+ 0 - 1
src/wellknowntypes/CMakeLists.txt

@@ -1,5 +1,4 @@
 set(TARGET QtProtobufWellKnownTypes)
-set(TARGET_STATIC ${TARGET}Static)
 set(TARGET_EXPORT ${TARGET}Targets)
 set(TARGET_CONFIG ${TARGET}Config)
 

+ 4 - 0
tests/test_qml/CMakeLists.txt

@@ -15,6 +15,10 @@ if(TARGET QtProtobufProject::QtProtobufWellKnownTypes)
     target_link_libraries(${TARGET} PRIVATE QtProtobufProject::QtProtobufWellKnownTypes)
 endif()
 
+if(QT_PROTOBUF_STATIC)
+    target_link_libraries(${TARGET} PRIVATE protobufquickplugin)
+endif()
+
 qtprotobuf_link_target(${TARGET} qtprotobuf_test_qtprotobuf_gen)
 
 add_target_qml(TARGET ${TARGET} QML_FILES ${QML_FILES})

+ 2 - 0
tests/test_qml/main.cpp

@@ -26,6 +26,7 @@
 #include <QtQuickTest>
 #include <QQmlEngine>
 #include <QQmlContext>
+#include <QQmlExtensionPlugin>
 
 #include "simpletest.qpb.h"
 
@@ -36,6 +37,7 @@ class TestSetup : public QObject {
 public:
     TestSetup() {
         QtProtobuf::qRegisterProtobufTypes();
+        Q_PROTOBUF_IMPORT_QUICK_PLUGIN()
     }
     ~TestSetup() = default;
 public slots: