Browse Source

Add static build support

- Add switch to static build by enabling QT_PROTOBUF_STATIC
  TODO: supported by linux only
- Fix issues in target_include_directories cmake rules for
  qtprotobuf_generate
- Add missed well-known types header files installation to system
  paths
- Update README

Fixes: #41
Alexey Edelev 5 years ago
parent
commit
ea043108db

+ 7 - 5
README.md

@@ -228,7 +228,7 @@ Due to cmake restrictions it's required to specify resulting artifacts manually
 
 *PROTO_FILES* - List of .proto files that will be used in generation procedure
 
-**Options**
+**Options:**
 
 *MULTI* - Enables multi-files generation mode. If provided in parameter list generator will create pair of header/source files for each message
 
@@ -242,7 +242,7 @@ Due to cmake restrictions it's required to specify resulting artifacts manually
 
 qtprotobuf_link_archive is cmake helper function that links whole archive to your library or executable target. It's useful when you try to link generated target to shared library or/and to executable that doesn't utilize all protobuf generated classes directly from C++ code, but requires them from QML.
 
-**Parameters**
+**Parameters:**
 
 *TARGET* - name of target to link to
 
@@ -251,11 +251,13 @@ qtprotobuf_link_archive is cmake helper function that links whole archive to you
 
 ### Usefull definitions
 
-*QTPROTOBUF_MAKE_COVERAGE* - if **TRUE/ON**, QtProtobuf will be built with gcov intergration, to collect code coverage reports(usefull for developers). **FALSE** by default
+*QTPROTOBUF_MAKE_COVERAGE* - if **TRUE/ON** for QtProtobuf project build, QtProtobuf will be built with gcov intergration, to collect code coverage reports(usefull for developers). **FALSE** by default
+
+*QTPROTOBUF_MAKE_TESTS* - if **TRUE/ON** for QtProtobuf project build, tests for QtProtobuf will be built. **TRUE** by default
 
-*QTPROTOBUF_MAKE_TESTS* - if **TRUE/ON**, tests for QtProtobuf will be built. **TRUE** by default
+*QTPROTOBUF_MAKE_EXAMPLES* - if **TRUE/ON** for QtProtobuf project build, built-in examples will be built. **TRUE** by default
 
-*QTPROTOBUF_MAKE_EXAMPLES* - if **TRUE/ON**, built-in examples will be built. **TRUE** by default
+*QT_PROTOBUF_STATIC* - if **TRUE/ON** for QtProtobuf project build, static libraries will be produced for all QtProtobuf targets except qml plugin. **FALSE** by default
 
 *QTPROTOBUF_EXECUTABLE* - contains full path to QtProtobuf generator add_executable
 

+ 4 - 4
cmake/GenerateQtHeaders.cmake

@@ -1,18 +1,18 @@
 function(protobuf_generate_qt_headers)
     set(options)
     set(oneValueArgs COMPONENT)
-    set(multiValueArgs PUBLIC_HEADERS)
+    set(multiValueArgs PUBLIC_HEADER)
     cmake_parse_arguments(protobuf_generate_qt_headers "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
 
-    foreach(PUBLIC_HEADER IN LISTS protobuf_generate_qt_headers_PUBLIC_HEADERS)
+    foreach(PUBLIC_HEADER IN LISTS protobuf_generate_qt_headers_PUBLIC_HEADER)
         get_filename_component(PUBLIC_HEADER_BASE_NAME ${PUBLIC_HEADER} NAME FALSE)
         file(STRINGS ${PUBLIC_HEADER} CLASS_NAME REGEX "#pragma once //[a-zA-Z]+")
         if (NOT "${CLASS_NAME}" STREQUAL "")
             string(REPLACE "#pragma once //" "" CLASS_NAME "${CLASS_NAME}")
             message("-- Generate Qt header for ${CLASS_NAME}")
             configure_file("${QTPROTOBUF_CMAKE_DIR}/GeneratedHeaderTemplate" "${QTPROTOBUF_BINARY_DIR}/include/${protobuf_generate_qt_headers_COMPONENT}/${CLASS_NAME}" @ONLY)
-            set(GENERATED_PUBLIC_HEADERS ${GENERATED_PUBLIC_HEADERS} ${QTPROTOBUF_BINARY_DIR}/include/${protobuf_generate_qt_headers_COMPONENT}/${CLASS_NAME})
+            set(GENERATED_PUBLIC_HEADER ${GENERATED_PUBLIC_HEADER} ${QTPROTOBUF_BINARY_DIR}/include/${protobuf_generate_qt_headers_COMPONENT}/${CLASS_NAME})
         endif()
     endforeach()
-    set(GENERATED_PUBLIC_HEADERS ${GENERATED_PUBLIC_HEADERS} PARENT_SCOPE)
+    set(GENERATED_PUBLIC_HEADER ${GENERATED_PUBLIC_HEADER} PARENT_SCOPE)
 endfunction()

+ 7 - 7
cmake/QtProtobufCommon.cmake

@@ -77,17 +77,17 @@ if(WIN32)
 endif()
 endfunction()
 
-if(NOT DEFINED QT_QMAKE_EXECUTABLE)
-    find_program(QT_QMAKE_EXECUTABLE "qmake")
-    if(QT_QMAKE_EXECUTABLE STREQUAL QT_QMAKE_EXECUTABLE-NOTFOUND)
-        message(FATAL_ERROR "Could not find qmake executable")
-    endif()
-endif()
-
 function(extract_qt_variable VARIABLE)
+    if(NOT DEFINED QT_QMAKE_EXECUTABLE)
+        find_program(QT_QMAKE_EXECUTABLE "qmake")
+        if(QT_QMAKE_EXECUTABLE STREQUAL QT_QMAKE_EXECUTABLE-NOTFOUND)
+            message(FATAL_ERROR "Could not find qmake executable")
+        endif()
+    endif()
     execute_process(
         COMMAND ${QT_QMAKE_EXECUTABLE} -query ${VARIABLE}
         OUTPUT_VARIABLE ${VARIABLE}
         OUTPUT_STRIP_TRAILING_WHITESPACE
     )
+    set(${VARIABLE} ${${VARIABLE}} PARENT_SCOPE)
 endfunction()

+ 12 - 4
cmake/QtProtobufGen.cmake

@@ -127,13 +127,21 @@ function(qtprotobuf_generate)
     list(APPEND GENERATED_SOURCES ${MOC_SOURCES})
     set_source_files_properties(${QTPROTOBUF_GENERATED_SOURCES} PROPERTIES GENERATED TRUE)
     add_library(${GENERATED_TARGET_NAME} ${QTPROTOBUF_GENERATED_SOURCES} ${MOC_SOURCES})
+    set_target_properties(${GENERATED_TARGET_NAME} PROPERTIES PUBLIC_HEADER "${QTPROTOBUF_GENERATED_HEADERS}")
     add_dependencies(${GENERATED_TARGET_NAME} ${GEN_TARGET})
     target_include_directories(${GENERATED_TARGET_NAME} PUBLIC ${OUT_DIR} PRIVATE ${Qt5Core_INCLUDE_DIRS}
-        $<TARGET_PROPERTY:${QTPROTOBUF_COMMON_NAMESPACE}::QtProtobuf,INTERFACE_INCLUDE_DIRECTORIES>
-        $<TARGET_PROPERTY:${QTPROTOBUF_COMMON_NAMESPACE}::QtGrpc,INTERFACE_INCLUDE_DIRECTORIES> ${OUT_DIR})
-    if(NOT WIN32)
+        $<TARGET_PROPERTY:${QTPROTOBUF_COMMON_NAMESPACE}::QtProtobuf,INTERFACE_INCLUDE_DIRECTORIES>)
+
+    if(TARGET ${QTPROTOBUF_COMMON_NAMESPACE}::QtGrpc)
         target_include_directories(${GENERATED_TARGET_NAME} PRIVATE
-            $<TARGET_PROPERTY:${QTPROTOBUF_COMMON_NAMESPACE}::QtProtobufWellKnownTypes,INTERFACE_INCLUDE_DIRECTORIES>)
+            $<TARGET_PROPERTY:${QTPROTOBUF_COMMON_NAMESPACE}::QtGrpc,INTERFACE_INCLUDE_DIRECTORIES>)
+    endif()
+
+    if(NOT WIN32)
+        if(TARGET ${QTPROTOBUF_COMMON_NAMESPACE}::QtProtobufWellKnownTypes)
+            target_include_directories(${GENERATED_TARGET_NAME} PRIVATE
+                $<TARGET_PROPERTY:${QTPROTOBUF_COMMON_NAMESPACE}::QtProtobufWellKnownTypes,INTERFACE_INCLUDE_DIRECTORIES>)
+        endif()
     endif()
     if(DEFINED qtprotobuf_generate_TARGET)
         qtprotobuf_link_archive(${qtprotobuf_generate_TARGET} ${GENERATED_TARGET_NAME})

+ 2 - 3
examples/qmakeexample/main.cpp

@@ -25,12 +25,11 @@
 
 #include <QCoreApplication>
 
-#include "qtprotobuf_global.qpb.h"
+#include <QtProtobufTypes>
 
 int main(int argc, char *argv[])
 {
-    qtprotobufnamespace::tests::qRegisterProtobufTypes();
-    qtprotobufnamespace::tests2::qRegisterProtobufTypes();
+    QtProtobuf::qRegisterProtobufTypes();
     QCoreApplication a(argc, argv);
     return a.exec();
 }

+ 13 - 4
src/grpc/CMakeLists.txt

@@ -41,16 +41,19 @@ file(GLOB HEADERS qgrpcasyncoperationbase_p.h
     qgrpcuserpasswordcredentials.h
     qtgrpcglobal.h)
 
-protobuf_generate_qt_headers(PUBLIC_HEADERS ${HEADERS} COMPONENT ${TARGET})
+protobuf_generate_qt_headers(PUBLIC_HEADER ${HEADERS} COMPONENT ${TARGET})
 
-add_library(${TARGET} SHARED ${SOURCES})
+if(QT_PROTOBUF_STATIC AND NOT WIN32)
+    add_library(${TARGET} STATIC ${SOURCES})
+else()
+    add_library(${TARGET} SHARED ${SOURCES})
+endif()
 
 extract_qt_variable(QT_HOST_DATA)
 
 target_compile_definitions(${TARGET} PRIVATE QT_BUILD_GRPC_LIB)
 
-add_library(${QTPROTOBUF_COMMON_NAMESPACE}::${TARGET} ALIAS ${TARGET})
-set_target_properties(${TARGET} PROPERTIES VERSION ${PROJECT_VERSION} PUBLIC_HEADER "${HEADERS};${GENERATED_PUBLIC_HEADERS}" OUTPUT_NAME ${TARGET})
+set_target_properties(${TARGET} PROPERTIES VERSION ${PROJECT_VERSION} PUBLIC_HEADER "${HEADERS};${GENERATED_PUBLIC_HEADER}" OUTPUT_NAME ${TARGET})
 target_include_directories(${TARGET} PUBLIC 
     $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
     $<BUILD_INTERFACE:${QTPROTOBUF_BINARY_DIR}/include/${TARGET}>
@@ -65,6 +68,9 @@ target_compile_features(${TARGET} PUBLIC cxx_std_14
                                          cxx_nullptr
                                          cxx_lambdas
                                          cxx_func_identifier)
+
+add_library(${QTPROTOBUF_COMMON_NAMESPACE}::${TARGET} ALIAS ${TARGET})
+
 install(TARGETS ${TARGET}
     EXPORT ${TARGET_EXPORT}
     ARCHIVE DESTINATION ${TARGET_LIB_DIR}
@@ -86,6 +92,9 @@ export(TARGETS ${TARGET} NAMESPACE ${QTPROTOBUF_COMMON_NAMESPACE}:: FILE ${TARGE
 configure_file("${QTPROTOBUF_CMAKE_DIR}/gRPCLookup.cmake" "${QTPROTOBUF_BINARY_DIR}/gRPCLookup.cmake" COPYONLY)
 install(FILES "${QTPROTOBUF_BINARY_DIR}/gRPCLookup.cmake" DESTINATION "${TARGET_CMAKE_DIR}")
 
+if(QT_PROTOBUF_STATIC) #extra config for .pri file in case if static build enabled
+    set(QTPROTOBUF_EXTRA_CONFIG "staticlib")
+endif()
 configure_file("${CMAKE_CURRENT_SOURCE_DIR}/qt_lib_grpc.pri.in" "${QTPROTOBUF_BINARY_DIR}/qt_lib_grpc.pri" @ONLY)
 install(FILES "${QTPROTOBUF_BINARY_DIR}/qt_lib_grpc.pri" DESTINATION "${QT_HOST_DATA}/mkspecs/modules")
 

+ 2 - 0
src/grpc/qt_lib_grpc.pri.in

@@ -5,4 +5,6 @@ QT.grpc.includes = @CMAKE_INSTALL_PREFIX@/@TARGET_INCLUDE_DIR@
 QT.grpc.private_includes =
 QT.grpc.libs = @CMAKE_INSTALL_PREFIX@/@TARGET_LIB_DIR@
 QT.grpc.depends = core network protobuf
+QT.grpc.module_config = @QTPROTOBUF_EXTRA_CONFIG@
+
 CONFIG += c++14

+ 16 - 6
src/protobuf/CMakeLists.txt

@@ -44,7 +44,7 @@ file(GLOB HEADERS
     qprotobufmetaobject.h
     qprotobufserializationplugininterface.h)
 
-file(GLOB PUBLIC_HEADERS
+file(GLOB PUBLIC_HEADER
     qtprotobufglobal.h
     qtprotobuftypes.h
     qtprotobuflogging.h
@@ -59,9 +59,13 @@ file(GLOB PUBLIC_HEADERS
     qprotobufmetaobject.h
     qprotobufserializationplugininterface.h)
 
-protobuf_generate_qt_headers(PUBLIC_HEADERS ${PUBLIC_HEADERS} COMPONENT ${TARGET})
+protobuf_generate_qt_headers(PUBLIC_HEADER ${PUBLIC_HEADER} COMPONENT ${TARGET})
 
-add_library(${TARGET} SHARED ${SOURCES})
+if(QT_PROTOBUF_STATIC AND NOT WIN32)
+    add_library(${TARGET} STATIC ${SOURCES})
+else()
+    add_library(${TARGET} SHARED ${SOURCES})
+endif()
 
 if(NOT DEFINED QT_QMAKE_EXECUTABLE)
     find_program(QT_QMAKE_EXECUTABLE "qmake")
@@ -79,14 +83,13 @@ target_compile_definitions(${TARGET} PUBLIC QT_PROTOBUF_PLUGIN_PATH="${QT_INSTAL
 target_compile_definitions(${TARGET} PRIVATE QT_BUILD_PROTOBUF_LIB PUBLIC QTPROTOBUF_VERSION_MAJOR=${PROJECT_VERSION_MAJOR}
     QTPROTOBUF_VERSION_MINOR=${PROJECT_VERSION_MINOR})
 
-add_library(${QTPROTOBUF_COMMON_NAMESPACE}::${TARGET} ALIAS ${TARGET})
-set_target_properties(${TARGET} PROPERTIES VERSION ${PROJECT_VERSION} PUBLIC_HEADER "${PUBLIC_HEADERS};${GENERATED_PUBLIC_HEADERS}" OUTPUT_NAME ${TARGET})
+set_target_properties(${TARGET} PROPERTIES VERSION ${PROJECT_VERSION} PUBLIC_HEADER "${PUBLIC_HEADER};${GENERATED_PUBLIC_HEADER}" OUTPUT_NAME ${TARGET})
 target_include_directories(${TARGET} PUBLIC
     $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
     $<BUILD_INTERFACE:${QTPROTOBUF_BINARY_DIR}/include/${TARGET}>
     $<INSTALL_INTERFACE:${TARGET_INCLUDE_DIR}>
 )
-target_link_libraries(${TARGET} PUBLIC Qt5::Core Qt5::Qml)
+
 target_compile_features(${TARGET} PUBLIC cxx_std_14
                                          cxx_auto_type
                                          cxx_decltype
@@ -96,6 +99,10 @@ target_compile_features(${TARGET} PUBLIC cxx_std_14
                                          cxx_lambdas
                                          cxx_func_identifier)
 
+target_link_libraries(${TARGET} PUBLIC Qt5::Core Qt5::Qml)
+
+add_library(${QTPROTOBUF_COMMON_NAMESPACE}::${TARGET} ALIAS ${TARGET})
+
 install(TARGETS ${TARGET}
     EXPORT ${TARGET_EXPORT}
     ARCHIVE DESTINATION ${TARGET_LIB_DIR}
@@ -123,6 +130,9 @@ install(FILES "${QTPROTOBUF_BINARY_DIR}/parsemessages.go" DESTINATION "${TARGET_
 configure_file("${QTPROTOBUF_CMAKE_DIR}/ProtobufLookup.cmake" "${QTPROTOBUF_BINARY_DIR}/ProtobufLookup.cmake" COPYONLY)
 install(FILES "${QTPROTOBUF_BINARY_DIR}/ProtobufLookup.cmake" DESTINATION "${TARGET_CMAKE_DIR}")
 
+if(QT_PROTOBUF_STATIC) #extra config for .pri file in case if static build enabled
+    set(QTPROTOBUF_EXTRA_CONFIG "staticlib")
+endif()
 configure_file("${CMAKE_CURRENT_SOURCE_DIR}/qt_lib_protobuf.pri.in" "${QTPROTOBUF_BINARY_DIR}/qt_lib_protobuf.pri" @ONLY)
 install(FILES "${QTPROTOBUF_BINARY_DIR}/qt_lib_protobuf.pri" DESTINATION "${QT_HOST_DATA}/mkspecs/modules")
 

+ 2 - 0
src/protobuf/qt_lib_protobuf.pri.in

@@ -5,6 +5,8 @@ QT.protobuf.includes = @CMAKE_INSTALL_PREFIX@/@TARGET_INCLUDE_DIR@
 QT.protobuf.private_includes =
 QT.protobuf.libs = @CMAKE_INSTALL_PREFIX@/@TARGET_LIB_DIR@
 QT.protobuf.depends = core qml
+QT.protobuf.module_config = @QTPROTOBUF_EXTRA_CONFIG@
+
 CONFIG += c++14
 
 defineTest(qtprotobuf_generate) {

+ 23 - 13
src/wellknowntypes/CMakeLists.txt

@@ -26,7 +26,7 @@ file(GLOB SOURCES
 file(GLOB HEADERS
     qtprotobufwellknowntypes_global.qbp.h)
 
-file(GLOB PUBLIC_HEADERS
+file(GLOB PUBLIC_HEADER
     qtprotobufwellknowntypes_global.qbp.h)
 
 function(add_wellknowntype TYPENAME)
@@ -41,12 +41,20 @@ function(add_wellknowntype TYPENAME)
                 PROTO_FILES ${PROTO_FILE}
                 PROTO_INCLUDES -I${INCLUDE_DIR}
                 QML)
+            target_include_directories(${TYPENAME} PRIVATE
+                $<TARGET_PROPERTY:${QTPROTOBUF_COMMON_NAMESPACE}::QtProtobufWellKnownTypes,INTERFACE_INCLUDE_DIRECTORIES>)
+            get_target_property(GENERATED_PUBLIC_HEADER_PRIVATE ${TYPENAME} PUBLIC_HEADER)
+            set(GENERATED_PUBLIC_HEADER "${GENERATED_PUBLIC_HEADER};${GENERATED_PUBLIC_HEADER_PRIVATE}" PARENT_SCOPE)
             break()
         endif()
     endforeach()
 endfunction()
 
-add_library(${TARGET} SHARED ${SOURCES})
+if(QT_PROTOBUF_STATIC AND NOT WIN32)
+    add_library(${TARGET} STATIC ${SOURCES})
+else()
+    add_library(${TARGET} SHARED ${SOURCES})
+endif()
 
 add_wellknowntype(any)
 add_wellknowntype(duration)
@@ -63,23 +71,14 @@ add_wellknowntype(api)
 add_dependencies(api type source_context)
 
 
-protobuf_generate_qt_headers(PUBLIC_HEADERS ${PUBLIC_HEADERS} COMPONENT ${TARGET})
+protobuf_generate_qt_headers(PUBLIC_HEADER ${PUBLIC_HEADER} COMPONENT ${TARGET})
 
 target_compile_definitions(${TARGET} PRIVATE QT_BUILD_PROTOBUF_WELLKNOWNTYPES_LIB PUBLIC QTPROTOBUF_VERSION_MAJOR=${PROJECT_VERSION_MAJOR}
     QTPROTOBUF_VERSION_MINOR=${PROJECT_VERSION_MINOR})
 
-add_library(${QTPROTOBUF_COMMON_NAMESPACE}::${TARGET} ALIAS ${TARGET})
-set_target_properties(${TARGET} PROPERTIES VERSION ${PROJECT_VERSION} PUBLIC_HEADER "${PUBLIC_HEADERS};${GENERATED_PUBLIC_HEADERS}" OUTPUT_NAME ${TARGET}
+set_target_properties(${TARGET} PROPERTIES VERSION ${PROJECT_VERSION} PUBLIC_HEADER "${PUBLIC_HEADER};${GENERATED_PUBLIC_HEADER}" OUTPUT_NAME ${TARGET}
     PROTO_INCLUDES -I${QTPROTOBUF_SOURCE_DIR}/3rdparty/grpc/third_party/protobuf/src)
-set_target_properties(${TARGET} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
-target_include_directories(${TARGET} PUBLIC
-    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
-    $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/generated>
-    $<BUILD_INTERFACE:${QTPROTOBUF_BINARY_DIR}/include/${TARGET}>
-    $<INSTALL_INTERFACE:${TARGET_INCLUDE_DIR}>
-    )
 
-target_link_libraries(${TARGET} PUBLIC Qt5::Core Qt5::Qml ${QTPROTOBUF_COMMON_NAMESPACE}::QtProtobuf)
 target_compile_features(${TARGET} PUBLIC cxx_std_14
     cxx_auto_type
     cxx_decltype
@@ -89,6 +88,17 @@ target_compile_features(${TARGET} PUBLIC cxx_std_14
     cxx_lambdas
     cxx_func_identifier)
 
+target_include_directories(${TARGET} PUBLIC
+    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
+    $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/generated>
+    $<BUILD_INTERFACE:${QTPROTOBUF_BINARY_DIR}/include/${TARGET}>
+    $<INSTALL_INTERFACE:${TARGET_INCLUDE_DIR}>
+    )
+
+add_library(${QTPROTOBUF_COMMON_NAMESPACE}::${TARGET} ALIAS ${TARGET})
+
+target_link_libraries(${TARGET} PUBLIC Qt5::Core Qt5::Qml ${QTPROTOBUF_COMMON_NAMESPACE}::QtProtobuf)
+
 install(TARGETS ${TARGET}
     EXPORT ${TARGET_EXPORT}
     ARCHIVE DESTINATION ${TARGET_LIB_DIR}

+ 1 - 1
tests/test_qml/CMakeLists.txt

@@ -9,7 +9,7 @@ file(GLOB SOURCES main.cpp)
 file(GLOB QML_FILES qml/tst_simple.qml)
 
 add_executable(${TARGET} ${SOURCES} ${QML_FILES})
-target_link_libraries(${TARGET} PRIVATE Qt5::Core Qt5::Qml Qt5::Network Qt5::Quick Qt5::Test Qt5::QuickTest QtProtobufProject::QtProtobuf)
+target_link_libraries(${TARGET} PRIVATE Qt5::Core Qt5::Qml Qt5::Network Qt5::Quick Qt5::Test Qt5::QuickTest QtProtobufProject::QtProtobuf QtProtobufProject::QtProtobufWellKnownTypes)
 qtprotobuf_link_archive(${TARGET} qtprotobuf_test_qtprotobuf_gen)
 
 add_target_qml(TARGET ${TARGET} QML_FILES ${QML_FILES})