Browse Source

Migrate to cmake build system

Alexey Edelev 3 years ago
parent
commit
a25a7f976b

+ 30 - 0
CMakeLists.txt

@@ -0,0 +1,30 @@
+cmake_minimum_required(VERSION 3.6)
+
+set(QT_TWAIN_VERSION 0.1.0)
+set(QT_TWAIN_PROJECT QtTWAINProject)
+
+project(${QT_TWAIN_PROJECT} VERSION ${QT_TWAIN_VERSION} LANGUAGES CXX)
+
+include(GNUInstallDirs)
+
+set(QT_TWAIN_CMAKE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+set(QT_TWAIN_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
+set(QT_TWAIN_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
+
+if(Qt5_POSITION_INDEPENDENT_CODE)
+    set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
+endif()
+set(CMAKE_CXX_STANDARD 14)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+add_subdirectory(src)
+add_subdirectory(examples)
+
+include(CMakePackageConfigHelpers)
+configure_package_config_file(
+    "${CMAKE_CURRENT_SOURCE_DIR}/ProjectConfig.cmake.in" "${QT_TWAIN_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
+    INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake")
+install(FILES "${QT_TWAIN_BINARY_DIR}/${PROJECT_NAME}Config.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
+    COMPONENT dev)
+
+export(PACKAGE ${PROJECT_NAME})

+ 3 - 0
ProjectConfig.cmake.in

@@ -0,0 +1,3 @@
+foreach(component ${@PROJECT_NAME@_FIND_COMPONENTS})
+  include(${CMAKE_CURRENT_LIST_DIR}/${component}Config.cmake)
+endforeach()

+ 18 - 0
cmake/GenerateQtHeaders.cmake

@@ -0,0 +1,18 @@
+function(generate_qt_headers)
+    set(options)
+    set(oneValueArgs COMPONENT)
+    set(multiValueArgs PUBLIC_HEADER)
+    cmake_parse_arguments(generate_qt_headers "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+    foreach(PUBLIC_HEADER IN LISTS 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(STATUS "Generate Qt header for ${CLASS_NAME}")
+            configure_file("${QT_TWAIN_CMAKE_DIR}/GeneratedHeaderTemplate" "${QT_TWAIN_BINARY_DIR}/include/${generate_qt_headers_COMPONENT}/${CLASS_NAME}" @ONLY)
+            set(GENERATED_PUBLIC_HEADER ${GENERATED_PUBLIC_HEADER} ${QT_TWAIN_BINARY_DIR}/include/${generate_qt_headers_COMPONENT}/${CLASS_NAME})
+        endif()
+    endforeach()
+    set(GENERATED_PUBLIC_HEADER ${GENERATED_PUBLIC_HEADER} PARENT_SCOPE)
+endfunction()

+ 1 - 0
cmake/GeneratedHeaderTemplate

@@ -0,0 +1 @@
+#include "@PUBLIC_HEADER_BASE_NAME@" 

+ 34 - 0
cmake/QtTWAINCommon.cmake

@@ -0,0 +1,34 @@
+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()
+
+function(add_target_windeployqt)
+if(WIN32)
+    set(options)
+    set(oneValueArgs QML_DIR TARGET)
+    set(multiValueArgs)
+    cmake_parse_arguments(add_target_windeployqt "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+    find_program(WINDEPLOYQT_EXECUTABLE "windeployqt" PATHS ${PATH})
+    if(WINDEPLOYQT_EXECUTABLE STREQUAL WINDEPLOYQT_EXECUTABLE-NOTFOUND)
+        message(WARNING "windeployqt is not found in specified PATH! Please, copy dependencies manually")
+    else()
+        if(DEFINED add_target_windeployqt_QML_DIR)
+            set(QML_DIR --qmldir ${add_target_windeployqt_QML_DIR})
+        endif()
+        add_custom_command(TARGET ${add_target_windeployqt_TARGET} POST_BUILD
+            COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:QtTWAIN> $<TARGET_FILE_DIR:${add_target_windeployqt_TARGET}>
+            COMMAND ${WINDEPLOYQT_EXECUTABLE} ${QML_DIR} $<TARGET_FILE_DIR:${add_target_windeployqt_TARGET}>)
+    endif()
+endif()
+endfunction()

+ 17 - 0
examples/CMakeLists.txt

@@ -0,0 +1,17 @@
+set(TARGET simplescan)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTORCC ON)
+
+find_package(Qt5 COMPONENTS Core Quick Qml REQUIRED)
+find_package(QtTWAINProject CONFIG REQUIRED COMPONENTS QtTWAIN)
+
+file(GLOB SOURCES main.cpp
+    scanengine.cpp)
+
+add_executable(${TARGET} ${SOURCES} qml.qrc)
+
+add_target_windeployqt(TARGET ${TARGET} QML_DIR ${CMAKE_CURRENT_SOURCE_DIR}/qml)
+
+target_link_libraries(${TARGET} PRIVATE examples_common QtTWAINProject::QtTWAIN Qt5::Quick Qt5::Qml)

+ 0 - 0
main.cpp → examples/main.cpp


+ 0 - 0
main.qml → examples/main.qml


+ 0 - 0
qml.qrc → examples/qml.qrc


+ 0 - 0
scanengine.cpp → examples/scanengine.cpp


+ 0 - 0
scanengine.h → examples/scanengine.h


+ 91 - 0
src/CMakeLists.txt

@@ -0,0 +1,91 @@
+set(TARGET QtTWAIN)
+set(TARGET_EXPORT ${TARGET}Targets)
+set(TARGET_CONFIG ${TARGET}Config)
+
+set(TARGET_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR}/${TARGET})
+set(TARGET_LIB_DIR ${CMAKE_INSTALL_LIBDIR})
+set(TARGET_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
+set(TARGET_BINDIR ${CMAKE_INSTALL_BINDIR})
+
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTORCC ON)
+
+find_package(Qt5 COMPONENTS Core Gui REQUIRED)
+
+include(${QT_TWAIN_CMAKE_DIR}/GenerateQtHeaders.cmake)
+include(${QT_TWAIN_CMAKE_DIR}/QtTWAINCommon.cmake)
+
+file(GLOB SOURCES
+    qtwaincontext.cpp
+    qtwaineventfilter.cpp
+    qtwainscanner.cpp
+    qtwainscannermanager.cpp
+    qtwainscanner_p.cpp
+    dsm/qdsminterface.cpp)
+
+file(GLOB HEADERS
+    twain.h
+    qtwaincontext_p.h
+    qtwaineventfilter_p.h
+    qtwain_p.h
+    qtwainscanner_p.h
+    dsm/qdsminterface.h)
+
+file(GLOB PUBLIC_HEADER
+    qtwainglobal.h
+    qtwainscanner.h
+    qtwainscannermanager.h)
+
+generate_qt_headers(PUBLIC_HEADER ${PUBLIC_HEADER} COMPONENT ${TARGET})
+
+add_library(${TARGET} SHARED ${SOURCES})
+
+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()
+
+extract_qt_variable(QT_HOST_DATA)
+
+target_compile_definitions(${TARGET} PRIVATE QT_BUILD_TWAIN_LIB PUBLIC QT_TWAIN_VERSION_MAJOR=${PROJECT_VERSION_MAJOR}
+    QT_TWAIN_VERSION_MINOR=${PROJECT_VERSION_MINOR})
+
+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:${QT_TWAIN_BINARY_DIR}/include/${TARGET}>
+    $<INSTALL_INTERFACE:${TARGET_INCLUDE_DIR}>
+)
+
+target_compile_features(${TARGET} PUBLIC cxx_std_14
+                                         cxx_auto_type
+                                         cxx_decltype
+                                         cxx_final
+                                         cxx_override
+                                         cxx_nullptr
+                                         cxx_lambdas
+                                         cxx_func_identifier)
+
+target_link_libraries(${TARGET} PUBLIC Qt5::Core Qt5::Gui)
+
+add_library(${QT_TWAIN_PROJECT}::${TARGET} ALIAS ${TARGET})
+
+install(TARGETS ${TARGET}
+    EXPORT ${TARGET_EXPORT} COMPONENT dev
+    ARCHIVE DESTINATION ${TARGET_LIB_DIR} COMPONENT lib
+    PUBLIC_HEADER DESTINATION ${TARGET_INCLUDE_DIR} COMPONENT dev
+    LIBRARY DESTINATION ${TARGET_LIB_DIR} COMPONENT lib
+    RUNTIME DESTINATION ${TARGET_BINDIR} COMPONENT lib)
+
+install(EXPORT ${TARGET_EXPORT} NAMESPACE ${QT_TWAIN_PROJECT}:: FILE ${TARGET_EXPORT}.cmake DESTINATION ${TARGET_CMAKE_DIR} COMPONENT dev)
+
+include(CMakePackageConfigHelpers)
+configure_package_config_file(
+    "${TARGET_CONFIG}.cmake.in" "${QT_TWAIN_BINARY_DIR}/${TARGET_CONFIG}.cmake"
+    INSTALL_DESTINATION "${TARGET_CMAKE_DIR}")
+
+install(FILES "${QT_TWAIN_BINARY_DIR}/${TARGET_CONFIG}.cmake" DESTINATION "${TARGET_CMAKE_DIR}" COMPONENT dev)
+
+export(TARGETS ${TARGET} NAMESPACE ${QT_TWAIN_PROJECT}:: FILE ${TARGET_EXPORT}.cmake)

+ 6 - 0
src/QtTWAINConfig.cmake.in

@@ -0,0 +1,6 @@
+if(NOT TARGET @TARGET@ AND NOT @TARGET@_BINARY_DIR)
+    include("${CMAKE_CURRENT_LIST_DIR}/@TARGET_EXPORT@.cmake")
+endif()
+
+@PACKAGE_INIT@
+set(QT_TWAIN_PROJECT "@QT_TWAIN_PROJECT@")

+ 32 - 0
src/qttwainglobal.h

@@ -0,0 +1,32 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020 Alexey Edelev <semlanik@gmail.com>
+ *
+ * This file is part of QtTWAIN project https://git.semlanik.org/semlanik/QtTWAIN
+ *
+ * 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
+
+#ifdef QT_BUILD_TWAIN_LIB
+    #define Q_TWAIN_EXPORT Q_DECL_EXPORT
+#else
+    #define Q_TWAIN_EXPORT Q_DECL_IMPORT
+#endif

+ 0 - 0
src/qtwainglobal.h → src/qtwaindefs.h


+ 3 - 2
src/qtwainscanner.h

@@ -28,7 +28,8 @@
 #include <QObject>
 #include <QImage>
 
-#include "qtwainglobal.h"
+#include "qttwainglobal.h"
+#include "qtwaindefs.h"
 
 #include <memory>
 
@@ -36,7 +37,7 @@ namespace QtTWAIN {
 class QTWAINScannerPrivate;
 class QTWAINContext;
 
-class QTWAINScanner final : public QObject
+Q_TWAIN_EXPORT class QTWAINScanner final : public QObject
 {
     Q_OBJECT
 public:

+ 3 - 1
src/qtwainscannermanager.h

@@ -29,11 +29,13 @@
 
 #include <qwindowdefs.h>
 
+#include "qttwainglobal.h"
+
 namespace QtTWAIN {
 
 class QTWAINScanner;
 
-class QTWAINScannerManager final
+Q_TWAIN_EXPORT class QTWAINScannerManager final
 {
 public:
     static void init(WId winId);

+ 0 - 36
twainapp.pro

@@ -1,36 +0,0 @@
-TEMPLATE = app
-
-QT += quick
-
-CONFIG += c++11
-
-INCLUDEPATH += src
-
-RESOURCES += \
-    qml.qrc
-
-SOURCES += \
-    main.cpp \
-    scanengine.cpp
-
-DISTFILES += \
-    main.qml
-
-HEADERS += \
-    scanengine.h \
-    src/dsm/qdsminterface.h \
-    src/qtwain_p.h \
-    src/qtwaincontext_p.h \
-    src/qtwaineventfilter_p.h \
-    src/qtwainglobal.h \
-    src/qtwainscanner.h \
-    src/qtwainscanner_p.h \
-    src/qtwainscannermanager.h
-
-SOURCES += \
-    src/dsm/qdsminterface.cpp \
-    src/qtwaincontext.cpp \
-    src/qtwaineventfilter.cpp \
-    src/qtwainscanner.cpp \
-    src/qtwainscanner_p.cpp \
-    src/qtwainscannermanager.cpp