瀏覽代碼

CPack: Improve packaging script (#1173)

- Packaging uses linuxdeploy.
- Drop template files and include it inside CMake script.
- Support better packaging on Windows and MSVC2017.
- Add comments about supported CMake minimum versions.
- Improve Mac OSX packaging script.

Signed-off-by: Hiroshi Miura <[email protected]>
Hiroshi Miura 5 年之前
父節點
當前提交
cb41c64aeb
共有 5 個文件被更改,包括 128 次插入158 次删除
  1. 1 0
      CMakeLists.txt
  2. 0 8
      CPackLinuxDeployQt.cmake.in
  3. 0 3
      CPackMacDeployQt.cmake.in
  4. 91 127
      Packaging.cmake
  5. 36 20
      src/CMakeLists.txt

+ 1 - 0
CMakeLists.txt

@@ -1,3 +1,4 @@
+cmake_policy(SET CMP0042 NEW)
 cmake_minimum_required (VERSION 3.13)
 project(VNote VERSION 2.8.2
         DESCRIPTION "VNote is a markdown note taking application"

+ 0 - 8
CPackLinuxDeployQt.cmake.in

@@ -1,8 +0,0 @@
-execute_process(COMMAND ${CMAKE_MAKE_PROGRAM} DESTDIR=${CPACK_PACKAGE_DIRECTORY}/_CPack_Packages/Linux/External/AppImage install
-                WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
-execute_process(COMMAND "${LINUXDEPLOYQT_EXECUTABLE}" ${CPACK_PACKAGE_DIRECTORY}/_CPack_Packages/Linux/External/AppImage${CMAKE_INSTALL_PREFIX}/share/applications/vnote.desktop -bundle-non-qt-libs -qmake=${_qmake_executable}
-                # hot fix for a known issue for libnss3 and libnssutils3.
-                COMMAND ${CMAKE_COMMAND} -E copy_directory ${NSS3_PLUGIN_PATH} ${CPACK_PACKAGE_DIRECTORY}/_CPack_Packages/Linux/External/AppImage${CMAKE_INSTALL_PREFIX}/lib/
-                COMMAND "${LINUXDEPLOYQT_EXECUTABLE}"  ${CPACK_PACKAGE_DIRECTORY}/_CPack_Packages/Linux/External/AppImage${CMAKE_INSTALL_PREFIX}/share/applications/vnote.desktop -appimage -qmake=${_qmake_executable}
-                 WORKING_DIRECTORY ${CPACK_PACKAGE_DIRECTORY}
-                )

+ 0 - 3
CPackMacDeployQt.cmake.in

@@ -1,3 +0,0 @@
-execute_process(COMMAND "${MACDEPLOYQT_EXECUTABLE}" ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.app -dmg
-                 WORKING_DIRECTORY ${CPACK_PACKAGE_DIRECTORY}
-                )

+ 91 - 127
Packaging.cmake

@@ -1,77 +1,6 @@
-
 find_package(Qt5Core REQUIRED)
 get_target_property(_qmake_executable Qt5::qmake IMPORTED_LOCATION)
 get_filename_component(_qt_bin_dir "${_qmake_executable}" DIRECTORY)
-find_program(WINDEPLOYQT_EXECUTABLE windeployqt HINTS "${_qt_bin_dir}")
-find_program(LINUXDEPLOYQT_EXECUTABLE linuxdeployqt linuxdeployqt-continuous-x86_64.AppImage HINTS "${_qt_bin_dir}")
-find_program(MACDEPLOYQT_EXECUTABLE macdeployqt HINTS "${_qt_bin_dir}")
-find_program(MACDEPLOYQTFIX_EXECUTABLE macdeployqtfix.py HINTS "${_qt_bin_dir}")
-find_package(Python)
-
-set(CPACK_IFW_ROOT $ENV{HOME}/Qt/QtIFW-3.0.6/ CACHE PATH "Qt Installer Framework installation base path")
-find_program(BINARYCREATOR_EXECUTABLE binarycreator HINTS "${_qt_bin_dir}" ${CPACK_IFW_ROOT}/bin)
-
-mark_as_advanced(WINDEPLOYQT_EXECUTABLE LINUXDEPLOYQT_EXECUTABLE)
-mark_as_advanced(MACDEPLOYQT_EXECUTABLE MACDEPLOYQTFIX_EXECUTABLE)
-
-function(linuxdeployqt destdir desktopfile)
-    # creating AppDir
-    add_custom_command(TARGET bundle PRE_BUILD
-                       COMMAND "${CMAKE_MAKE_PROGRAM}" DESTDIR=${destdir} install
-                       COMMAND "${LINUXDEPLOYQT_EXECUTABLE}" ${destdir}/${CMAKE_INSTALL_PREFIX}/${desktopfile} -bundle-non-qt-libs
-                               -qmake=${_qmake_executable}
-                       # hot fix for a known issue for libnss3 and libnssutils3.
-                       COMMAND ${CMAKE_COMMAND} -E copy_directory ${NSS3_PLUGIN_PATH}
-                                                                  ${destdir}/${CMAKE_INSTALL_PREFIX}/lib/
-                       WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
-    # packaging AppImage
-    add_custom_command(TARGET bundle POST_BUILD
-                       COMMAND "${LINUXDEPLOYQT_EXECUTABLE}"  ${destdir}/${CMAKE_INSTALL_PREFIX}/${desktopfile}
-                               -appimage -qmake=${_qmake_executable}
-                       WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/packaging)
-endfunction()
-
-function(windeployqt target)
-
-    # Bundle Library Files
-    if(CMAKE_BUILD_TYPE_UPPER STREQUAL "DEBUG")
-        set(WINDEPLOYQT_ARGS --debug)
-    else()
-        set(WINDEPLOYQT_ARGS --release)
-    endif()
-
-    add_custom_command(TARGET ${target} POST_BUILD
-                       COMMAND "${CMAKE_COMMAND}" -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/winqt/"
-                       COMMAND "${CMAKE_COMMAND}" -E
-                               env PATH="${_qt_bin_dir}" "${WINDEPLOYQT_EXECUTABLE}"
-                               ${WINDEPLOYQT_ARGS}
-                               --verbose 0
-                               --no-compiler-runtime
-                               --no-angle
-                               --no-opengl-sw
-                               --dir "${CMAKE_CURRENT_BINARY_DIR}/winqt/"
-                               $<TARGET_FILE:${target}>
-                       COMMENT "Deploying Qt..."
-    )
-    install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/winqt/" DESTINATION bin)
-    set(CMAKE_INSTALL_UCRT_LIBRARIES TRUE)
-    include(InstallRequiredSystemLibraries)
-endfunction()
-
-function(macdeployqt bundle targetdir _PACKAGER)
-    file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/CPackMacDeployQt-${_PACKAGER}.cmake
-         CONTENT "set(APP_BUNDLE_DIR \"${CPACK_PACKAGE_DIRECTORY}/_CPack_Packages/Darwin/${_PACKAGER}/${targetdir}/${bundle}\")
-                  execute_process(
-                    COMMAND \"${MACDEPLOYQT_EXECUTABLE}\" \"${APP_BUNDLE_DIR}}\" -always-overwrite
-                    COMMAND ${Python_EXECUTABLE} \"${MACDEPLOYQTFIX_EXECUTABLE}\" \"${APP_BUNDLE_DIR}/Contents/MacOS/VNote\" ${qt_bin_dir}/../
-                    COMMAND \"${MACDEPLOYQT_EXECUTABLE}\" \"${APP_BUNDLE_DIR}>/Contents/Frameworks/QtWebEngineCore.framework/Versions/5/Helpers/QtWebEngineProcess.app
-                    COMMAND ${Python_EXECUTABLE} \"${MACDEPLOYQTFIX_EXECUTABLE}\" \"${APP_BUNDLE_DIR}>/Contents/Frameworks/QtWebEngineCore.framework/Versions/5/Helpers/QtWebEngineProcess.app/Contents/MacOS/QtWebEngineProcess\" ${qt_bin_dir}/../
-                  )"
-    )
-
-    install(SCRIPT ${CMAKE_BINARY_DIR}/CPackMacDeployQt-${_PACKAGER}.cmake COMPONENT Runtime)
-    include(InstallRequiredSystemLibraries)
-endfunction()
 
 set(CPACK_PACKAGE_VENDOR "Le Tan")
 set(CPACK_PACKAGE_NAME "vnote")
@@ -102,6 +31,8 @@ add_custom_target(bundle
 set(CPACK_GENERATOR)
 
 # Qt IFW packaging framework
+set(CPACK_IFW_ROOT $ENV{HOME}/Qt/QtIFW-3.0.6/ CACHE PATH "Qt Installer Framework installation base path")
+find_program(BINARYCREATOR_EXECUTABLE binarycreator HINTS "${_qt_bin_dir}" ${CPACK_IFW_ROOT}/bin)
 if(BINARYCREATOR_EXECUTABLE)
     list(APPEND CPACK_GENERATOR IFW)
     message(STATUS "   + Qt Installer Framework               YES ")
@@ -109,9 +40,10 @@ else()
     message(STATUS "   + Qt Installer Framework                NO ")
 endif()
 
-if(WIN32 AND NOT UNIX)
+if (WIN32 AND NOT UNIX)
     #--------------------------------------------------------------------------
     # Windows specific
+    find_program(WINDEPLOYQT_EXECUTABLE windeployqt HINTS "${_qt_bin_dir}" DOC "Path to the windeployqt utility")
     list(APPEND CPACK_GENERATOR ZIP)
     message(STATUS "Package generation - Windows")
     message(STATUS "   + ZIP                                  YES ")
@@ -123,11 +55,9 @@ if(WIN32 AND NOT UNIX)
     if(NSIS_PATH)
         list(APPEND CPACK_GENERATOR NSIS)
         message(STATUS "   + NSIS                                 YES ")
-
         set(CPACK_NSIS_DISPLAY_NAME ${CPACK_PACKAGE_NAME})
-        # Icon of the installer
-        file(TO_NATIVE_PATH "${PACKAGE_ICON}" CPACK_NSIS_MUI_ICON)
-        file(TO_NATIVE_PATH "${PACKAGE_ICON}" CPACK_NSIS_MUI_HEADERIMAGE_BITMAP)
+        set(CPACK_NSIS_MUI_ICON "${PACKAGE_ICON}")
+        set(CPACK_NSIS_MUI_HEADERIMAGE_BITMAP "${PACKAGE_ICON}")
         set(CPACK_NSIS_CONTACT "${CPACK_PACKAGE_CONTACT}")
         set(CPACK_NSIS_MODIFY_PATH ON)
     else()
@@ -144,35 +74,56 @@ if(WIN32 AND NOT UNIX)
         message(STATUS "   + NuGET                                NO ")
     endif()
 
-    windeployqt(VNote)
+    # Bundle Library Files
+    if(CMAKE_BUILD_TYPE_UPPER STREQUAL "DEBUG")
+        set(WINDEPLOYQT_ARGS --debug)
+    else()
+        set(WINDEPLOYQT_ARGS --release)
+    endif()
+    file(MAKE_DIRECTORY "${CPACK_PACKAGE_DIRECTORY}/_qtstaff")
+    add_custom_command(TARGET bundle PRE_BUILD
+                       COMMAND "${CMAKE_COMMAND}" -E
+                       env PATH="${_qt_bin_dir}" "${WINDEPLOYQT_EXECUTABLE}"
+                       ${WINDEPLOYQT_ARGS}
+                       --verbose 0
+                       --no-compiler-runtime
+                       --no-angle
+                       --no-opengl-sw
+                       --dir "${CPACK_PACKAGE_DIRECTORY}/_qtstaff"
+                       $<TARGET_FILE:VNote>
+                       COMMENT "Deploying Qt..."
+                       )
+    install(DIRECTORY "${CPACK_PACKAGE_DIRECTORY}/_qtstaff/" DESTINATION bin)
+    set(CMAKE_INSTALL_UCRT_LIBRARIES TRUE)
+    include(InstallRequiredSystemLibraries)
 
-elseif(APPLE)
+elseif (APPLE)
     #--------------------------------------------------------------------------
     # Apple specific
+    find_program(MACDEPLOYQT_EXECUTABLE macdeployqt HINTS "${_qt_bin_dir}" DOC "Path to the macdeployqt utility")
+    find_program(MACDEPLOYQTFIX_EXECUTABLE macdeployqtfix.py HINTS "${_qt_bin_dir}" DOC "Path to the macdeployqtfix utility")
+    find_package(Python2 REQUIRED COMPONENTS Interpreter)
     message(STATUS "Package generation - Mac OS X")
-    message(STATUS "   + TBZ2                                 YES ")
-
-    list(APPEND CPACK_GENERATOR TBZ2)
     set(CPACK_PACKAGE_ICON ${CMAKE_SOURCE_DIR}/resources/Icon.icns)
-    set(CMAKE_INSTALL_RPATH "@executable_path/../Frameworks")
-    macdeployqt("${PROJECT_NAME}.app" "${PROJECT_NAME}-${PROJECT_VERSION}-Darwin" "TBZ")
-
-    # XXX: not working settings for bundle and dragndrop generator
-    set(CPACK_BUNDLE_NAME "${PROJECT_NAME}" )
-    set(CPACK_BUNDLE_PLIST "${CMAKE_BINARY_DIR}/Info.plist")
-    set(CPACK_BUNDLE_ICON ${CMAKE_PACKAGE_ICON})
-    set(CPACK_DMG_VOLUME_NAME "${PROJECT_NAME}")
-    set(CPACK_DMG_FORMAT "UDBZ")
-    set(CPACK_DMG_BACKGROUND_IMAGE "${CMAKE_SOURCE_DIR}/src/resources/icons/vnote.png")
-
-    if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.13)
-        list(APPEND CPACK_GENERATOR External)
-        message(STATUS "   + macdeployqt -dmg                     YES ")
-        configure_file(${CMAKE_SOURCE_DIR}/CPackMacDeployQt.cmake.in "${CMAKE_BINARY_DIR}/CPackExternal.cmake")
-        set(CPACK_EXTERNAL_PACKAGE_SCRIPT "${CMAKE_BINARY_DIR}/CPackExternal.cmake")
-    endif()
+    list(APPEND CPACK_GENERATOR External)
+    set(CPACK_EXTERNAL_ENABLE_STAGING ON)
+    set(CPACK_SET_DESTDIR ON)
+    message(STATUS "   + macdeployqt -dmg                     YES ")
+    set(EXTERNAL_WORK "_CPack_Packages/Darwin/External/${CPACK_PACKAGE_NAME}-${PROJECT_VERSION}-Darwin")
+    set(APP_BUNDLE "${CPACK_PACKAGE_DIRECTORY}/${EXTERNAL_WORK}/${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.app")
+    string(FIND "${Qt5_DIR}" "/cmake/Qt5" _STR_LOC)
+    string(SUBSTRING "${Qt5_DIR}" 0 ${_STR_LOC} _QT_LIB_ROOT)
+    file(GENERATE OUTPUT  "${CMAKE_BINARY_DIR}/CPackExternal.cmake"
+         CONTENT "execute_process(COMMAND \"${MACDEPLOYQT_EXECUTABLE}\" \"${APP_BUNDLE}\" -always-overwrite -verbose=2 -libpath=${_QT_LIB_ROOT})
+                  execute_process(COMMAND ${Python2_EXECUTABLE} \"${MACDEPLOYQTFIX_EXECUTABLE}\" \"${APP_BUNDLE}/Contents/MacOS/VNote\" ${_QT_LIB_ROOT} -v)
+                  execute_process(COMMAND \"${MACDEPLOYQT_EXECUTABLE}\" \"${APP_BUNDLE}/Contents/Frameworks/QtWebEngineCore.framework/Versions/5/Helpers/QtWebEngineProcess.app\" -verbose=2 -libpath=${_QT_LIB_ROOT})
+                  execute_process(COMMAND ${Python2_EXECUTABLE} \"${MACDEPLOYQTFIX_EXECUTABLE}\" \"${APP_BUNDLE}/Contents/Frameworks/QtWebEngineCore.framework/Versions/5/Helpers/QtWebEngineProcess.app/Contents/MacOS/QtWebEngineProcess\" ${_QT_LIB_ROOT} -v)
+                  execute_process(COMMAND \"${MACDEPLOYQT_EXECUTABLE}\" \"${APP_BUNDLE}\" -dmg -verbose=2 -always-overwrite -libpath=${_QT_LIB_ROOT})"
+         )
+    set(CPACK_EXTERNAL_PACKAGE_SCRIPT "${CMAKE_BINARY_DIR}/CPackExternal.cmake")
+    include(InstallRequiredSystemLibraries)
 
-else()
+else ()
     #-----------------------------------------------------------------------------
     # Linux specific
     list(APPEND CPACK_GENERATOR TBZ2 TXZ)
@@ -189,39 +140,52 @@ else()
         message(STATUS "   + RPM                                  NO ")
     endif()
 
-    list(APPEND CPACK_GENERATOR DEB)
-    message(STATUS "   + DEB                                  YES ")
-    # use default, that is an output of `dpkg --print-architecture`
-    #set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
-    set(CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION TRUE)
-    set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://tamlok.github.io/vnote")
-    # check if dependencies exist in standard path, i.e standard package
-    # ubuntu bionic or later has it.
-    find_path(QT5WEBENGINEWIDGET_PATH
-              NAMES libQt5WebEngineWidgets.so
-              PATHS /usr/lib/${CMAKE_LIBRARY_ARCHITECTURE} /usr/lib
-              NO_DEFAULT_PATH)
-    if(QT5WEBENGINEWIDGET_PATH)
-        set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
-    else()
-        set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS OFF)
-        set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5core5a, libqt5gui5, libqt5positioning5, libqt5webenginewidgets5")
+    find_program(DEBUILD_PATH debuild)
+    if(DEBUILD_PATH)
+        list(APPEND CPACK_GENERATOR DEB)
+        message(STATUS "   + DEB                                  YES ")
+        # use default, that is an output of `dpkg --print-architecture`
+        #set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
+        set(CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION TRUE)
+        set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://tamlok.github.io/vnote")
+        if(Qt5_DIR STREQUAL "/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/cmake/Qt5" )
+            set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
+        else()
+            set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS OFF)
+            set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5core5a, libqt5gui5, libqt5positioning5, libqt5webenginewidgets5")
+        endif()
+        set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "graphviz")
+        set(CPACK_DEBIAN_PACKAGE_SUGGESTS "libjs-mathjax")
+        set(CPACK_DEBIAN_PACKAGE_SECTION "utils")
     endif()
-    set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "graphviz")
-    set(CPACK_DEBIAN_PACKAGE_SUGGESTS "libjs-mathjax")
-    set(CPACK_DEBIAN_PACKAGE_SECTION "utils")
 
-    if(LINUXDEPLOYQT_EXECUTABLE)
+    find_program(LINUXDEPLOY_EXECUTABLE linuxdeploy linuxdeploy-x86_64.AppImage HINTS "${_qt_bin_dir}")
+    if(LINUXDEPLOY_EXECUTABLE)
         message(STATUS "   + AppImage                             YES ")
         find_path(NSS3_PLUGIN_PATH NAMES libsoftokn3.so PATHS /usr/lib/${CMAKE_LIBRARY_ARCHITECTURE} /usr/lib /usr/local/lib
                   PATH_SUFFIXES nss NO_DEFAULT_PATH)
-        if(CMAKE_VERSION VERSION_LESS 3.13)
-            linuxdeployqt("${CPACK_PACKAGE_DIRECTORY}/_CPack_Packages/Linux/AppImage" "share/applications/vnote.desktop")
-        else()
-            set(CPACK_GENERATOR "External;${CPACK_GENERATOR}")
-            configure_file(${CMAKE_SOURCE_DIR}/CPackLinuxDeployQt.cmake.in "${CMAKE_BINARY_DIR}/CPackExternal.cmake")
-            set(CPACK_EXTERNAL_PACKAGE_SCRIPT "${CMAKE_BINARY_DIR}/CPackExternal.cmake")
-        endif()
+        set(CPACK_GENERATOR "External;${CPACK_GENERATOR}")
+        # run make DESTDIR=<CPACK_INSTALL_PREFIX> install before run package script
+        set(CPACK_EXTERNAL_ENABLE_STAGING ON)
+        set(CPACK_SET_DESTDIR ON)
+        set(_EXTERNAL_PACKDIR ${CPACK_PACKAGE_DIRECTORY}/_CPack_Packages/Linux/External/${CPACK_PACKAGE_NAME}-${PROJECT_VERSION}-Linux)
+        string(FIND "${Qt5_DIR}" "/cmake/Qt5" _STR_LOC)
+        string(SUBSTRING "${Qt5_DIR}" 0 ${_STR_LOC} _QT_LIB_ROOT)
+        set(_LINUXDEPLOY_ENV "QMAKE=${_qmake_executable}" "LD_LIBRARY_PATH=${_QT_LIB_ROOT}:$ENV{LD_LIBRARY_PATH}")
+        file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/CPackExternal.cmake"
+             CONTENT "execute_process(COMMAND ${CMAKE_COMMAND} -E env ${_LINUXDEPLOY_ENV} \"${LINUXDEPLOY_EXECUTABLE}\" --plugin qt --output appimage
+                                            -v1
+                                            --appdir ${_EXTERNAL_PACKDIR} -e  ${_EXTERNAL_PACKDIR}${CMAKE_INSTALL_PREFIX}/bin/VNote
+                                            --desktop-file ${_EXTERNAL_PACKDIR}${CMAKE_INSTALL_PREFIX}/share/applications/vnote.desktop
+                                            -i ${CMAKE_SOURCE_DIR}/src/resources/icons/16x16/vnote.png -i ${CMAKE_SOURCE_DIR}/src/resources/icons/32x32/vnote.png
+                                            -i ${CMAKE_SOURCE_DIR}/src/resources/icons/48x48/vnote.png -i ${CMAKE_SOURCE_DIR}/src/resources/icons/64x64/vnote.png
+                                            -i ${CMAKE_SOURCE_DIR}/src/resources/icons/128x128/vnote.png -i ${CMAKE_SOURCE_DIR}/src/resources/icons/256x256/vnote.png
+                                            -i ${CMAKE_SOURCE_DIR}/src/resources/icons/vnote.svg
+                                            -l ${NSS3_PLUGIN_PATH}/libfreebl3.so -l ${NSS3_PLUGIN_PATH}/libfreeblpriv3.so -l ${NSS3_PLUGIN_PATH}/libnssckbi.so
+                                            -l ${NSS3_PLUGIN_PATH}/libnssdbm3.so -l ${NSS3_PLUGIN_PATH}/libsoftokn3.so
+                                      WORKING_DIRECTORY ${CPACK_PACKAGE_DIRECTORY})"
+             )
+        set(CPACK_EXTERNAL_PACKAGE_SCRIPT "${CMAKE_BINARY_DIR}/CPackExternal.cmake")
     else()
         message(STATUS "   + AppImage                              NO ")
     endif()

+ 36 - 20
src/CMakeLists.txt

@@ -1,15 +1,17 @@
-add_executable(VNote main.cpp)
+add_executable(VNote MACOSX_BUNDLE main.cpp)
 
 file(GLOB SRC_FILES *.cpp)
 file(GLOB DIALOG_SRCS dialog/*.cpp)
 file(GLOB UTILS_SRCS utils/*.cpp)
 file(GLOB WIDGETS_SRCS widgets/*.cpp)
+file(GLOB QRC_FILES *.qrc)
+file(GLOB TRANSLATIONS translations/*.qm)
 
 target_sources(VNote PRIVATE ${SRC_FILES})
 target_sources(VNote PRIVATE ${DIALOG_SRCS})
 target_sources(VNote PRIVATE ${UTILS_SRCS})
 target_sources(VNote PRIVATE ${WIDGETS_SRCS})
-target_sources(VNote PRIVATE vnote.qrc translations.qrc)
+target_sources(VNote PRIVATE ${QRC_FILES})
 
 include_directories(dialog utils widgets)
 
@@ -29,11 +31,39 @@ if(GCC_VERSION VERSION_GREATER_EQUAL 8.0)
   target_compile_options(VNote PRIVATE "-Wno-class-memaccess")
 endif()
 
-## INSTALLS
-install(TARGETS VNote RUNTIME DESTINATION bin)
-install(FILES translations/vnote_zh_CN.qm translations/vnote_ja.qm DESTINATION translations )
+if (WIN32 AND NOT UNIX)
+    # MSVC and not mingw32
+    install(TARGETS VNote RUNTIME DESTINATION bin)
+    install(FILES ${TRANSLATIONS} DESTINATION translations )
+elseif (APPLE)
+    set_target_properties(VNote PROPERTIES MACOSX_PACKAGE_LOCATION "${PROJECT_NAME}.app/Contents")
+    if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+        set(CMAKE_INSTALL_PREFIX "/Applications" CACHE PATH "Reset installation path to MacOS default." FORCE)
+    endif()
+    install(TARGETS VNote BUNDLE DESTINATION . COMPONENT Runtime
+            RUNTIME DESTINATION bin COMPONENT Runtime)
+    install(FILES ${TRANSLATIONS} DESTINATION translations COMPONENT Runtime)
+    set(MACOSX_BUNDLE_BUNDLE_NAME "VNote")
+    set(MACOSX_BUNDLE_BUNDLE_GUI_IDENTIFIER "com.tamlok.VNote")
+    set(MACOSX_BUNDLE_ICON_FILE ${CMAKE_SOURCE_DIR}/src/resources/icons/vnote.icns)
+    set(MACOSX_BUNDLE_BUNDLE_VERSION "VNOTE ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
+    set(MACOSX_BUNDLE_LONG_VERSION_STRING ${MACOSX_BUNDLE_BUNDLE_VERSION})
+    # Set short version independent with project version to be able to increment independendently.
+    math(EXPR SHORT_VERSION_MAJOR "${PROJECT_VERSION_MAJOR} * 100 + ${PROJECT_VERSION_MINOR}")
+    set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${SHORT_VERSION_MAJOR}.${PROJECT_VERSION_PATCH}.0")
+    set(MACOSX_BUNDLE_EXECUTABLE_NAME "VNote")
+    set(MACOSX_BUNDLE_COPYRIGHT "Distributed under MIT license. Copyright 2016-2019 Le Tan")
+    set(MACOSX_BUNDLE_INFO_STRING "VNote is a note-taking application that knows programmers and Markdown better. Distributed under MIT license. Copyright 2017 Le Tan")
+
+    set_source_files_properties(${MACOSX_BUNDLE_ICON_FILE} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
+else()
+    # Linux, mingw32
+    if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+        set(CMAKE_INSTALL_PREFIX "/usr" CACHE PATH "Reset installation path to MacOS default." FORCE)
+    endif()
+    install(TARGETS VNote RUNTIME DESTINATION bin)
+    install(FILES ${TRANSLATIONS} DESTINATION translations )
 
-if(UNIX AND NOT DARWIN)
     set(desktop.path applications)
     set(desktop.files vnote.desktop)
 
@@ -67,19 +97,5 @@ if(UNIX AND NOT DARWIN)
         DESTINATION share/doc/vnote/
         PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
         RENAME copyright)
-elseif(DARWIN)
-    set(MACOSX_BUNDLE_BUNDLE_NAME "VNote")
-    set(MACOSX_BUNDLE_BUNDLE_GUI_IDENTIFIER "com.tamlok.VNote")
-    set(MACOSX_BUNDLE_ICON_FILE ${CMAKE_SOURCE_DIR}/src/resources/icons/vnote.icns)
-    set(MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
-    set(MACOSX_BUNDLE_LONG_VERSION_STRING ${MACOSX_BUNDLE_BUNDLE_VERSION})
-    # Set short version independent with project version to be able to increment independendently.
-    math(EXPR SHORT_VERSION_MAJOR "${PROJECT_VERSION_MAJOR} * 100 + ${PROJECT_VERSION_MINOR}")
-    set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${SHORT_VERSION_MAJOR}.${PROJECT_VERSION_PATCH}.0")
-    set(MACOSX_BUNDLE_EXECUTABLE_NAME "VNote")
-    set(MACOSX_BUNDLE_COPYRIGHT "Distributed under MIT license. Copyright 2016-2019 Le Tan")
-    set(MACOSX_BUNDLE_INFO_STRING "VNote is a note-taking application that knows programmers and Markdown better. Distributed under MIT license. Copyright 2017 Le Tan")
-
-    set_source_files_properties(${MACOSX_BUNDLE_ICON_FILE} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
 endif()