Procházet zdrojové kódy

repo: 引入 Spark 构建,支持构建 deb

zinface před 2 roky
rodič
revize
2b28d310d6

+ 42 - 12
.gitignore

@@ -384,15 +384,45 @@ FodyWeavers.xsd
 !.vscode/extensions.json
 *.code-workspace
 
-# Local History for Visual Studio Code
-.history/
-
-# Windows Installer files from build outputs
-*.cab
-*.msi
-*.msix
-*.msm
-*.msp
-
-# JetBrains Rider
-*.sln.iml
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
+
+
+
+# Ignore the build directory generated by the vsocde cmake extension
+build/
+# Ignore the build directory generated by the vsocde clangd extension
+.cache
+
+# Created by https://www.toptal.com/developers/gitignore/api/cmake
+# Edit at https://www.toptal.com/developers/gitignore?templates=cmake
+
+### CMake ###
+CMakeLists.txt.user
+CMakeCache.txt
+CMakeFiles
+CMakeScripts
+Testing
+Makefile
+cmake_install.cmake
+install_manifest.txt
+compile_commands.json
+CTestTestfile.cmake
+_deps
+
+### CMake Patch ###
+# External projects
+*-prefix/
+
+# End of https://www.toptal.com/developers/gitignore/api/cmake
+!/Makefile

+ 33 - 3
CMakeLists.txt

@@ -1,5 +1,5 @@
-cmake_minimum_required(VERSION 3.16)
-project(notepad--)
+cmake_minimum_required(VERSION 3.24)
+project(notepad-- VERSION 1.22.0)
 
 set(CMAKE_AUTOMOC ON)
 set(CMAKE_AUTOUIC ON)
@@ -54,4 +54,34 @@ install(DIRECTORY  ${PROJECT_SOURCE_DIR}/src/linux/usr
 include(${PROJECT_SOURCE_DIR}/cmake/package_config.cmake) 
 include(CPack)
 
-target_link_libraries(${PROJECT_NAME} qscint Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Concurrent Qt5::Network  Qt5::PrintSupport Qt5::XmlPatterns)
+target_link_libraries(${PROJECT_NAME} qscint Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Concurrent Qt5::Network  Qt5::PrintSupport Qt5::XmlPatterns)
+
+if(CMAKE_HOST_UNIX)
+    include(cmake/SparkInstallMacrosConfig.cmake)
+    include(cmake/SparkDesktopMacros.cmake)
+    # 内容默认应用名称: Name= 应与项目名称相同
+    spark_desktop_macros(
+        # 应用名称: Name=
+        ${PROJECT_NAME}
+        # 应用名称: Name[zh_CN]=
+        "Notepad--"
+        # 应用说明: Comment=
+        "Notepad-- 是一个国产跨平台、简单的文本编辑器。"
+        # 应用类型: Type=
+        "Application"
+        # 执行程序: Exec=
+        "notepad--"
+        # 图标路径: Icon=
+        "/usr/share/notepad--/icons/spark.png"
+        # 应用分类: Category=
+        "Development"
+    )
+    spark_install_file(/usr/share/applications/    ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.desktop)
+    spark_install_file(/usr/share/notepad--/icons/ assets/spark.png)
+    spark_install_target(/usr/bin/ ${PROJECT_NAME})
+
+    # 注释行(使用方式)
+    find_package(DebPackage PATHS ${CMAKE_SOURCE_DIR})
+    add_package_descript(cmake/package-deb.descript)
+
+endif(CMAKE_HOST_UNIX)

+ 61 - 0
Makefile

@@ -0,0 +1,61 @@
+CPUS=$(shell nproc)
+CALENDAR=$(shell date '+%Y%m%d')
+OSID=$(shell lsb_release -si)
+OSRELEASE=$(shell lsb_release -sr)
+SUFFIX=
+ifneq ("$(OSID)", "")
+SUFFIX=_$(OSID)$(OSRELEASE)
+endif
+
+PROJECT_NAME=notepad--
+PACKAGE_NAME=com.hmja.notepad
+
+all:
+	mkdir -p build
+	cd build && cmake ..
+	cd build && make -j$(CPUS)
+
+run: all
+	exec $(shell find build/ -maxdepth 1 -type f -executable | grep $(PROJECT_NAME))
+
+debug:
+	mkdir -p build
+	cd build && cmake -DCMAKE_BUILD_TYPE=Debug ..
+	cd build && make -j$(CPUS)
+
+release:
+	mkdir -p build
+	cd build && cmake -DCMAKE_BUILD_TYPE=Release -DPACKAGE_SUFFIX="$(SUFFIX)" ..
+	cd build && make -j$(CPUS)
+
+package: release
+	cd build && make package
+	tree build/_CPack_Packages/Linux/DEB/$(PROJECT_NAME)-*
+	dpkg-deb --contents build/$(PACKAGE_NAME)_*$(CALENDAR)*$(SUFFIX).deb
+	# cd build/_CPack_Packages/Linux/DEB/$(PROJECT_NAME)_*$(CALENDAR)*$(SUFFIX).deb && find .
+
+builddeps:
+	cd build && make builddeps
+
+cpus:
+	@echo "CPU数量: $(CPUS)"
+
+copytosource:package
+	cp build/$(PACKAGE_NAME)_*$(CALENDAR)*.deb .
+
+# 进入 qdebug 模式,在 deepin 中默认被禁用,可 env | grep QT 查看,并在 /etc/X11/Xsession.d/00deepin-dde-env 配置中已定义
+# 1. 禁止 qt 的 debug 打印: qt.*.debug=false
+# 	qt.qpa.input.events
+#	qt.qpa.events
+# 2. 禁止 dtk 的 debug 打印: dtk.*.debug=false
+# 	dtk.dpluginloader
+# 3. 禁止 qtcreator 本身的 debug 打印
+# 	qtc.autotest.testcodeparser
+#	qtc.clangbackend.server
+#	...
+# 4. 关闭其它的太麻烦了,直接只启用本地 debug
+#	.debug=true
+enter-qdebug-mode:
+	# 进入新的 bash 环境
+	@# export QT_LOGGING_RULES=".debug=true; qt.*.debug=false; dtk.*.debug=false; dde.*.debug=false; qtc*=false; " && bash
+	export QT_LOGGING_RULES=".debug=true" && bash

binární
assets/spark.png


+ 323 - 0
cmake/DebPackageConfig.cmake

@@ -0,0 +1,323 @@
+cmake_minimum_required(VERSION 3.0.0)
+
+# function(add_deb_package PACKAGE_NAME PACKAGE_VERSION PACKAGE_MAINTAINER PACKAGE_EMAIL PACKAGE_SHORT_DESCRIPTION PACKAGE_LONG_DESCRIPTION)
+
+# endfunction(add_deb_package PACKAGE_NAME PACKAGE_VERSION PACKAGE_MAINTAINER PACKAGE_EMAIL PACKAGE_SHORT_DESCRIPTION PACKAGE_LONG_DESCRIPTION)
+
+# if(add_deb_package    VALUE) set(Package    ${VALUE} PARENT_SCOPE) endif(add_deb_package    VALUE)
+# if(add_deb_version    VALUE) set(Version    ${VALUE} PARENT_SCOPE) endif(add_deb_version    VALUE)
+# if(add_deb_maintainer VALUE) set(Maintainer ${VALUE} PARENT_SCOPE) endif(add_deb_maintainer VALUE)
+# if(add_deb_email      VALUE) set(Email      ${VALUE} PARENT_SCOPE) endif(add_deb_email      VALUE)
+# if(add_deb_descrition VALUE) set(Descrition ${VALUE} PARENT_SCOPE) endif(add_deb_descrition VALUE)
+# if(add_deb_detail     VALUE) set(Detail     ${VALUE} PARENT_SCOPE) endif(add_deb_detail     VALUE)
+
+
+# set(Package         "")
+# set(Version         "")
+# set(Architecture    "")
+# set(Maintainer      "")
+# set(Email           "")
+# set(Descrition      "")
+
+function(find_str _IN _SEP _OUT)
+    string(FIND "${_IN}" "${_SEP}" _TMP)
+    set(${_OUT} ${_TMP} PARENT_SCOPE)
+endfunction(find_str _IN _SEP _OUT)
+
+
+function(find_next _IN _OUT)
+    find_str("${_IN}" "\n" _TMP)
+    set(${_OUT} ${_TMP} PARENT_SCOPE)
+endfunction(find_next _IN _OUT)
+
+function(sub_next _IN _INDEX _OUT __OUT)
+    find_next(${_IN} _NEXTINDEX)
+    string(SUBSTRING "${_IN}" ${_INDEX} ${_NEXTINDEX} _TMP)
+    math(EXPR _NEXTINDEX ${_NEXTINDEX}+1)
+    string(SUBSTRING "${_IN}" ${_NEXTINDEX} -1 __TMP)
+    set(${_OUT} ${_TMP} PARENT_SCOPE)
+    set(${__OUT} ${__TMP} PARENT_SCOPE)
+endfunction(sub_next _IN _INDEX _OUT)
+
+function(trim_str _IN _OUT)
+    string(STRIP "${_IN}" _TMP)
+    set(${_OUT} ${_TMP} PARENT_SCOPE)
+endfunction(trim_str _IN _OUT)
+
+function(split_str _IN _SEP _OUT)
+    string(FIND "${_IN}" "${_SEP}" _TMP_INDEX)
+    if(NOT _TMP_INDEX EQUAL -1)
+        string(SUBSTRING "${_IN}" 0 ${_TMP_INDEX} _TMP)
+        math(EXPR _TMP_INDEX ${_TMP_INDEX}+1)
+        string(SUBSTRING "${_IN}" ${_TMP_INDEX} -1 __TMP)
+        set(${_OUT} "${_TMP};${__TMP}" PARENT_SCOPE)
+    else()
+        set(${_OUT} ${_IN} PARENT_SCOPE)
+    endif(NOT _TMP_INDEX EQUAL -1)
+endfunction(split_str _IN _SEP _OUT)
+
+function(split_str_p _IN _SEP _OUT __OUT)
+    split_str("${_IN}" "${_SEP}" _TMP)
+    list(GET _TMP 0 __TMP)
+    list(GET _TMP 1 ___TMP)
+    set(${_OUT} ${__TMP} PARENT_SCOPE)
+    set(${__OUT} ${___TMP} PARENT_SCOPE)
+endfunction(split_str_p _IN _SEP _OUT __OUT)
+
+function(split_str_n _IN _SEP _OUT _N)
+    if(_N GREATER 1)
+        set(_C ${_N})
+        set(_RET "")
+        set(_NEXT ${_IN})
+        while(NOT _C EQUAL 0)
+            split_str("${_NEXT}" "${_SEP}" _TMP)
+            list(LENGTH _TMP _TMP_LEN)
+            if(_TMP_LEN EQUAL 2)
+                list(GET _TMP 0 __TMP)
+                list(GET _TMP 1 _NEXT)
+                list(APPEND _RET ${__TMP})
+            else()
+                break()
+            endif(_TMP_LEN EQUAL 2)
+            math(EXPR _C "${_C}-1")
+        endwhile(NOT _C EQUAL 0)
+        list(APPEND _RET ${_NEXT})
+        set(${_OUT} ${_RET} PARENT_SCOPE)
+    else()
+        split_str("${_IN}" "${_SEP}" _TMP)
+        set(${_OUT} ${_TMP} PARENT_SCOPE)
+    endif(_N GREATER 1)
+endfunction(split_str_n _IN _SEP _OUT _N)
+
+
+function(set_package_vars _IN_KEY _IN_VAL)
+
+    # trim_str("${_IN_KEY}" _IN_KEY)
+
+    find_str("${_IN_KEY}" "Type" _Type)
+    if(_Type EQUAL "0")
+        string(TOUPPER "${_IN_VAL}" _IN_VAL_UPPER)
+        string(TOLOWER "${_IN_VAL}" _IN_VAL_LOWER)
+        set(CPACK_GENERATOR "${_IN_VAL_UPPER}" PARENT_SCOPE)
+        message("--> 软件包类型: ${_IN_VAL_LOWER}")
+    endif(_Type EQUAL "0")
+
+    find_str("${_IN_KEY}" "Package" _Package)
+    if(_Package EQUAL "0")
+        if(_IN_VAL STREQUAL "auto")
+            set(CPACK_DEBIAN_PACKAGE_NAME "${PROJECT_NAME}" PARENT_SCOPE)
+        else()
+            set(CPACK_DEBIAN_PACKAGE_NAME "${_IN_VAL}" PARENT_SCOPE)
+        endif(_IN_VAL STREQUAL "auto")
+        message("--> 软件包名: ${_IN_VAL}")
+    endif(_Package EQUAL "0")
+
+    find_str("${_IN_KEY}" "Version" _Version)
+    if(_Version EQUAL "0")
+        if(_IN_VAL STREQUAL "auto")
+            set(CPACK_DEBIAN_PACKAGE_VERSION "${PROJECT_VERSION}" PARENT_SCOPE)
+        else()
+            set(CPACK_DEBIAN_PACKAGE_VERSION "${_IN_VAL}" PARENT_SCOPE)
+        endif(_IN_VAL STREQUAL "auto")
+
+        message("--> 软件版本: ${_IN_VAL}")
+    endif(_Version EQUAL "0")
+
+    find_str("${_IN_KEY}" "CalVer" _CalVer)
+    if(_CalVer EQUAL "0")
+        set(CalVer "${_IN_VAL}" PARENT_SCOPE)
+        message("--> 日历化版本: ${_IN_VAL}")
+    endif(_CalVer EQUAL "0")
+
+    find_str("${_IN_KEY}" "Architecture" _Architecture)
+    if(_Architecture EQUAL "0")
+        set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "${_IN_VAL}" PARENT_SCOPE)
+        if(_IN_VAL STREQUAL "auto")
+            execute_process(
+                COMMAND dpkg --print-architecture
+                OUTPUT_VARIABLE _RETV
+                OUTPUT_STRIP_TRAILING_WHITESPACE
+            )
+            set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "${_RETV}" PARENT_SCOPE)
+        endif(_IN_VAL STREQUAL "auto")
+        message("--> 软件架构: ${_IN_VAL}")
+    endif(_Architecture EQUAL "0")
+
+    find_str("${_IN_KEY}" "Priority" _Priority)
+    if(_Priority EQUAL "0")
+        set(CPACK_DEBIAN_PACKAGE_PRIORITY "${_IN_VAL}" PARENT_SCOPE)
+        message("--> 优先级: ${_IN_VAL}")
+    endif(_Priority EQUAL "0")
+
+    find_str("${_IN_KEY}" "Depends" _Depends)
+    if(_Depends EQUAL "0")
+        set(CPACK_DEBIAN_PACKAGE_DEPENDS "${_IN_VAL}" PARENT_SCOPE)
+        message("--> 软件依赖: ${_IN_VAL}")
+    endif(_Depends EQUAL "0")
+
+    find_str("${_IN_KEY}" "Maintainer" _Maintainer)
+    if(_Maintainer EQUAL "0")
+        set(CPACK_DEBIAN_PACKAGE_MAINTAINER "${_IN_VAL}" PARENT_SCOPE)
+        message("--> 软件维护者: ${_IN_VAL}")
+    endif(_Maintainer EQUAL "0")
+
+    find_str("${_IN_KEY}" "Homepage" _Homepage)
+    if(_Homepage EQUAL "0")
+        set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "${_IN_VAL}" PARENT_SCOPE)
+        message("--> 软件主页: ${_IN_VAL}")
+    endif(_Homepage EQUAL "0")
+
+    find_str("${_IN_KEY}" "Recommends" _Recommends)
+    if(_Recommends EQUAL "0")
+        set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "${_IN_VAL}" PARENT_SCOPE)
+        message("--> 软件建议: ${_IN_VAL}")
+    endif(_Recommends EQUAL "0")
+
+endfunction(set_package_vars _IN_KEY _IN_VAL)
+
+# 定义一个自定义(add_package_descript)函数
+# 用于按特定配置约定自动化构建软件包配置
+function(add_package_descript IN_DES)
+    set(PACKAGE_DES_PATH "${IN_DES}")
+
+    if(EXISTS ${IN_DES})
+
+    elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${IN_DES}")
+        set(PACKAGE_DES_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${IN_DES}")
+    else()
+        message(FATAL_ERROR "!! Not Found Path: ${PACKAGE_DES_PATH}")
+        return()
+    endif(EXISTS ${IN_DES})
+
+    file(READ ${PACKAGE_DES_PATH} DES_CONTENT)
+    trim_str("${DES_CONTENT}" DES_CONTENT)
+
+    ################## 解析 ##################
+
+    sub_next(${DES_CONTENT} NEXT_INDEX DES_LINE DES_CONTENT)
+    set(PREV_DES "")
+    while(NOT DES_LINE STREQUAL "${PREV_DES}")
+        # 检查该描述行是否是 # 注释开头,是的话将跳过该行
+        find_str("${DES_LINE}" "#" _COMMENT)
+        if(_COMMENT EQUAL "0")
+            message("--> !!!!!!! ${DES_LINE}")
+            sub_next(${DES_CONTENT} NEXT_INDEX DES_LINE DES_CONTENT)
+            continue()
+        endif(_COMMENT EQUAL "0")
+
+        # 检查该描述行是否是 Descrition 开头,是的话说明描述结尾了
+        find_str("${DES_LINE}" "Descrition" _DESCRIPTION)
+        if(_DESCRIPTION EQUAL "0")
+            break()
+        endif(_DESCRIPTION EQUAL "0")
+
+        split_str_n("${DES_LINE}" ":" _TMP 1)
+        list(LENGTH _TMP _TMP_LEN)
+
+        if(_TMP_LEN EQUAL 2)
+            split_str_p("${DES_LINE}" ":" _TMP __TMP)
+            trim_str("${__TMP}" __TMP)
+            string(LENGTH "${__TMP}" __TMP_LENGTH)
+            if(NOT __TMP_LENGTH EQUAL "0")
+                set_package_vars("${_TMP}" "${__TMP}")
+            endif(NOT __TMP_LENGTH EQUAL "0")
+        endif(_TMP_LEN EQUAL 2)
+
+        # 记录当前行,获取下一行,可能是已经结尾了(将保持重复行)
+        set(PREV_DES "${DES_LINE}")
+        sub_next(${DES_CONTENT} NEXT_INDEX DES_LINE DES_CONTENT)
+    endwhile(NOT DES_LINE STREQUAL "${PREV_DES}")
+
+
+    # 再一次检查该描述行是否是 Descrition 开头,是的话将进行分析描述行
+    find_str("${DES_LINE}" "Descrition" _DESCRIPTION)
+    if(_DESCRIPTION EQUAL "0")
+        split_str_p("${DES_LINE}" ":" _TMP __TMP)
+        trim_str("${__TMP}" __TMP)
+        set(Descrition ${__TMP})
+        set(PREV_DES_LINE "")
+        while(NOT PREV_DES_LINE STREQUAL DES_LINE)
+            if(NOT PREV_DES_LINE STREQUAL "")
+                set(Descrition "${Descrition}\n${DES_LINE}")
+            endif(NOT PREV_DES_LINE STREQUAL "")
+            set(PREV_DES_LINE "${DES_LINE}")
+            sub_next(${DES_CONTENT} NEXT_INDEX DES_LINE DES_CONTENT)
+        endwhile(NOT PREV_DES_LINE STREQUAL DES_LINE)
+        # set(Descrition "${Descrition}")
+        message("--> 软件说明: ${Descrition}")
+
+        set(CPACK_DEBIAN_PACKAGE_DESCRIPTION ${Descrition})
+    endif(_DESCRIPTION EQUAL "0")
+
+    ##################### deb #####################
+    # ARCHITECTURE
+    if(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "x86_64")
+        set(ARCHITECTURE "amd64")
+    elseif(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "aarch64")
+        set(ARCHITECTURE "arm64")
+    endif()
+
+    #################### Calendar Version ###################
+    if("${CalVer}" STREQUAL "true")
+        string(TIMESTAMP BUILD_TIME "%Y%m%d")
+        set(CPACK_DEBIAN_PACKAGE_VERSION "${CPACK_DEBIAN_PACKAGE_VERSION}-${BUILD_TIME}")
+    endif("${CalVer}" STREQUAL "true")
+
+
+
+    ##################### deb file name #####################
+    set(_Package      "${CPACK_DEBIAN_PACKAGE_NAME}")
+    set(_Version      "${CPACK_DEBIAN_PACKAGE_VERSION}")
+    set(_Architecture "${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
+
+    set(_DebFileName
+        "${_Package}_${_Version}_${_Architecture}${PACKAGE_SUFFIX}.deb"
+    )
+    set(CPACK_DEBIAN_FILE_NAME            ${_DebFileName})
+
+
+    # set(CPACK_DEBIAN_PACKAGE_NAME         "${Package}")
+    # set(CPACK_DEBIAN_PACKAGE_VERSION      "${Version}")
+    # set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "${Architecture}")
+    # set(CPACK_DEBIAN_PACKAGE_DEPENDS      "${Depends}")
+    # set(CPACK_DEBIAN_PACKAGE_PRIORITY     "${Priority}")
+    # set(CPACK_DEBIAN_PACKAGE_MAINTAINER   "${Maintainer}")
+    # set(CPACK_DEBIAN_PACKAGE_DESCRIPTION  "${Descrition}")
+
+    # 设置即将使用的标准脚本
+    # set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA
+    #     "${CMAKE_SOURCE_DIR}/config/DEBIAN/preinst"
+    #     "${CMAKE_SOURCE_DIR}/config/DEBIAN/postinst"
+    #     "${CMAKE_SOURCE_DIR}/config/DEBIAN/prerm"
+    #     "${CMAKE_SOURCE_DIR}/config/DEBIAN/postrm"
+    # )
+
+    # 设置为ON,以便使用 dpkg-shlibdeps 生成更好的包依赖列表。
+    # set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
+    # set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON)
+    # set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS_POLICY "=")
+
+    include(CPack)
+
+endfunction(add_package_descript IN_DES)
+
+
+# TODO:
+# CPACK_GENERATOR
+# CPACK_DEBIAN_FILE_NAME                - n
+# CPACK_DEBIAN_PACKAGE_NAME             - y
+# CPACK_DEBIAN_PACKAGE_VERSION          - y
+# CPACK_DEBIAN_PACKAGE_ARCHITECTURE     - y(auto)
+# CPACK_DEBIAN_PACKAGE_DEPENDS          - y
+# CPACK_DEBIAN_PACKAGE_PRIORITY         - y
+# CPACK_DEBIAN_PACKAGE_MAINTAINER       - y
+# CPACK_DEBIAN_PACKAGE_DESCRIPTION      - y
+
+# ARCHITECTURE
+# if(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "x86_64")
+#     set(ARCHITECTURE "amd64")
+# elseif(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "aarch64")
+#     set(ARCHITECTURE "arm64")
+# endif()
+
+# string(TIMESTAMP BUILD_TIME "%Y%m%d")

+ 35 - 0
cmake/SparkDesktopMacros.cmake

@@ -0,0 +1,35 @@
+
+macro(spark_desktop_macros _APP_NAME _APP_NAME_ZH_CN _APP_COMMENT _APP_TYPE _APP_EXECUTE_PATH _APP_EXECUTE_ICON_PATH _APP_CATEGORIES)
+    set(APP_NAME ${_APP_NAME})
+    set(APP_NAME_ZH_CN ${_APP_NAME_ZH_CN})
+    set(APP_COMMENT ${_APP_COMMENT})
+    set(APP_TYPE ${_APP_TYPE})
+    set(APP_EXECUTE_PATH ${_APP_EXECUTE_PATH})
+    set(APP_EXECUTE_ICON_PATH ${_APP_EXECUTE_ICON_PATH})
+    set(APP_CATEGORIES ${_APP_CATEGORIES})
+    configure_file(cmake/spark-desktop.desktop.in
+        ${CMAKE_BINARY_DIR}/${_APP_NAME}.desktop
+    )
+endmacro(spark_desktop_macros _APP_NAME _APP_NAME_ZH_CN _APP_COMMENT _APP_TYPE _APP_EXECUTE_PATH _APP_EXECUTE_ICON_PATH _APP_CATEGORIES)
+
+# include(cmake/SparkDesktopMacros.cmake)
+# 内容默认应用名称: Name= 应与项目名称相同
+# spark_desktop_macros(
+    # 应用名称: Name=
+    # 应用名称: Name[zh_CN]=
+    # 应用说明: Comment=
+    # 应用类型: Type=
+    # 执行程序: Exec=
+    # 图标路径: Icon=
+    # 应用分类: Category=
+# )
+
+# configure_file(<input> <output>
+#                [NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS |
+#                 FILE_PERMISSIONS <permissions>...]
+#                [COPYONLY] [ESCAPE_QUOTES] [@ONLY]
+#                [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
+
+# install(FILES ${APP_NAME}.desktop
+#     DESTINATION /usr/share/applications
+# )

+ 131 - 0
cmake/SparkInstallMacrosConfig.cmake

@@ -0,0 +1,131 @@
+
+# spark_install_target
+# 基于传入的路径/目标进行安装
+# 可接受的值为: 安装路径 目标A
+# 可接受的值为: 安装路径 目标A 目标B 目标C...
+macro(spark_install_target INSTALL_TARGET_DIR INSTALL_TARGETS)
+    install(TARGETS
+        ${INSTALL_TARGETS} ${ARGN}
+        DESTINATION ${INSTALL_TARGET_DIR})
+endmacro(spark_install_target INSTALL_TARGET_DIR INSTALL_TARGETS)
+
+# spark_install_file
+# 基于传入的路径/文件进行安装
+# 可接受的值为: 安装路径 文件A
+# 可接受的值为: 安装路径 文件A 文件B 文件C...
+macro(spark_install_file INSTALL_FILE_DIR INSTALL_FILE)
+    install(FILES
+        ${INSTALL_FILE} ${ARGN}
+        DESTINATION ${INSTALL_FILE_DIR})
+endmacro(spark_install_file INSTALL_FILE_DIR INSTALL_FILE)
+
+# spark_install_program
+# 基于传入的路径/文件进行安装,并自动为其添加可执行权限
+# 可接受的值为: 安装路径 文件A
+# 可接受的值为: 安装路径 文件A 文件B 文件C...
+macro(spark_install_program INSTALL_PROGRAM_DIR INSTALL_PROGRAM)
+    install(PROGRAMS
+        ${INSTALL_PROGRAM} ${ARGN}
+        DESTINATION ${INSTALL_PROGRAM_DIR})
+endmacro(spark_install_program INSTALL_PROGRAM_DIR INSTALL_PROGRAM)
+
+
+# spark_install_directory
+# 基于传入的路径/目录进行安装
+# 可接受的值为: 安装路径 路径A
+# 可接受的值为: 安装路径 路径A/* 为安装路径A下所有内容
+macro(spark_install_directory INSTALL_DIRECTORY_DIR INSTALL_DIRECOTRY)
+    # INSTALL_DIRECOTRY 可能包含 * ?
+    # 1. 找到 '*', 截取,列出目录下所有文件,安装
+    # 2. 是文件的直接使用 spark_install_file 安装
+    # 2. 是目录的直接使用 spark_install_directory 安装
+    # message(FATAL_ERROR "${INSTALL_DIRECTORY_DIR}")
+    # string(FIND <string> <substring> <output_variable> [REVERSE])
+    string(FIND "${INSTALL_DIRECOTRY}" "*" INSTALL_DIRECTORY_FIND_INDEX)
+    # message(FATAL_ERROR "${INSTALL_DIRECTORY_FIND_INDEX}:  ${INSTALL_DIRECTORY_DIR}")
+
+    # file(GLOB <variable>
+    #  [LIST_DIRECTORIES true|false] [RELATIVE <path>] [CONFIGURE_DEPENDS]
+    #  [<globbing-expressions>...])
+
+    if (NOT INSTALL_DIRECTORY_FIND_INDEX EQUAL -1)
+        # string(SUBSTRING <string> <begin> <length> <output_variable>)
+        string(SUBSTRING "${INSTALL_DIRECOTRY}" 0 ${INSTALL_DIRECTORY_FIND_INDEX} INSTALL_DIRECTORY_FIND_INDEX_SUBSTRING)
+        # message(FATAL_ERROR "directory: ${INSTALL_DIRECTORY_FIND_INDEX_SUBSTRING}")
+
+        # file(GLOB <variable>
+        #     [LIST_DIRECTORIES true|false] [RELATIVE <path>] [CONFIGURE_DEPENDS]
+        #     [<globbing-expressions>...])
+
+        file(GLOB INSTALL_DIRECTORY_FIND_INDEX_SUBSTRING_FILE_GLOB_LIST  ${INSTALL_DIRECTORY_FIND_INDEX_SUBSTRING}/*)
+        list(LENGTH INSTALL_DIRECTORY_FIND_INDEX_SUBSTRING_FILE_GLOB_LIST INSTALL_DIRECTORY_FIND_INDEX_SUBSTRING_FILE_GLOB_LIST_LENGTH)
+        foreach(item IN LISTS INSTALL_DIRECTORY_FIND_INDEX_SUBSTRING_FILE_GLOB_LIST)
+            # message("-> ${item}")
+            if(IS_DIRECTORY ${item})
+                message("-> ${item} IS_DIRECTORY")
+                # spark_install_directory(${INSTALL_DIRECTORY_DIR} ${item})
+                install(DIRECTORY
+                    ${item}
+                    DESTINATION ${INSTALL_DIRECTORY_DIR}
+                    USE_SOURCE_PERMISSIONS)
+            else()
+                message("-> ${item} NOT IS_DIRECTORY")
+                spark_install_program(${INSTALL_DIRECTORY_DIR} ${item})
+                # spark_install_file(${INSTALL_DIRECTORY_DIR} ${item})
+            endif(IS_DIRECTORY ${item})
+        endforeach(item IN LISTS INSTALL_DIRECTORY_FIND_INDEX_SUBSTRING_FILE_GLOB_LIST)
+
+        # message(FATAL_ERROR " directory: ${INSTALL_DIRECTORY_FIND_INDEX_SUBSTRING_FILE_GLOB_LIST}")
+        # message(FATAL_ERROR " directory: ${INSTALL_DIRECTORY_FIND_INDEX_SUBSTRING_FILE_GLOB_LIST_LENGTH}")
+
+    else()
+        message(FATAL_ERROR "install: ${INSTALL_DIRECTORY_DIR}")
+
+        install(DIRECTORY
+            ${INSTALL_DIRECOTRY} ${ARGN}
+            DESTINATION ${INSTALL_DIRECTORY_DIR})
+    endif(NOT INSTALL_DIRECTORY_FIND_INDEX EQUAL -1)
+
+endmacro(spark_install_directory INSTALL_DIRECTORY_DIR INSTALL_DIRECOTRY)
+
+
+
+macro(spark_install_changelog CHANGE_LOG_FILE)
+    set(SOURCE_CHANGE_LOG_FILE ${CHANGE_LOG_FILE})
+    if (EXISTS ${SOURCE_CHANGE_LOG_FILE})
+
+        execute_process(COMMAND test -f ${SOURCE_CHANGE_LOG_FILE}
+            RESULT_VARIABLE changelog_test
+        )
+        execute_process(COMMAND which gzip
+            RESULT_VARIABLE gzip_test
+        )
+        if (NOT changelog_test  EQUAL 0)
+            message(FATAL_ERROR "NOTE: 不是常规文件: ${SOURCE_CHANGE_LOG_FILE}")
+        endif(NOT changelog_test  EQUAL 0)
+
+        if (NOT gzip_test  EQUAL 0)
+            message(FATAL_ERROR "NOTE: 未安装 gzip, 无法压缩 changelog")
+        endif(NOT gzip_test  EQUAL 0)
+
+        # 压缩与安装日志文件
+        add_custom_command(
+            OUTPUT "${CMAKE_BINARY_DIR}/changelog.gz"
+            COMMAND gzip -cn9 "${SOURCE_CHANGE_LOG_FILE}" > "${CMAKE_BINARY_DIR}/changelog.gz"
+            WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
+            COMMENT "Compressing changelog"
+        )
+        add_custom_target(changelog ALL DEPENDS "${CMAKE_BINARY_DIR}/changelog.gz")
+
+        # include(GNUInstallDirs)
+        set(SPARK_INSTALL_CHANGE_LOG_DIR "/usr/share/doc/${PROJECT_NAME}/")
+        install(FILES
+            ${CMAKE_BINARY_DIR}/changelog.gz
+            debian/copyright
+
+            DESTINATION ${SPARK_INSTALL_CHANGE_LOG_DIR}
+        )
+    else()
+        message(FATAL_ERROR "未找到: ${SOURCE_CHANGE_LOG_FILE}")
+    endif(EXISTS ${SOURCE_CHANGE_LOG_FILE})
+endmacro(spark_install_changelog CHANGE_LOG_FILE)

+ 45 - 0
cmake/package-deb.descript

@@ -0,0 +1,45 @@
+# 注释行(使用方式)
+# find_package(DebPackage PATHS ${CMAKE_SOURCE_DIR})
+# add_package_descript(cmake/package-deb.descript)
+
+# 打包后的文件名称
+# FileName: 待定
+# 配置 PACKAGE_SUFFIX 变量可添加尾巴名称
+# 如在 Makefile 中硬编码方式
+# OSID=$(shell lsb_release -si)
+# OSRELEASE=$(shell lsb_release -sr)
+# -DPACKAGE_SUFFIX="_$(OSID)$(OSRELEASE)"
+
+# deb 安装包的安装时脚本
+# 1.安装[前|后]执行脚本(preinst,postinst),
+# 2.卸载[前|后]执行脚本(prerm,postrm)
+# ControlExtra: 未定义(暂不支持)
+# 如需指定请修改 DebPackageConfig.cmake 模板(第252行)
+# CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA 变量
+
+# 打包类型,暂支持 deb, 未来支持 tgz(tar.gz)
+Type: deb
+# 软件包名称(自动, 使用 PROJECT_NAME 变量值)
+Package: com.hmja.notepad
+# 软件包版本(自动, 使用 PROJECT_VERSION 变量值)
+Version: auto
+# 日历化尾部版本
+CalVer: true
+# 软件包架构(自动)
+Architecture: auto
+# 软件包属于的系统部分[admin|cli-mono|comm|database|debug|devel|doc|editors|education|electronics|embedded|fonts|games|gnome|gnu-r|gnustep|graphics|hamradio|haskell|httpd|interpreters|introspection|java|javascript|kde|kernel|libdevel|libs|lisp|localization|mail|math|metapackages|misc|net|news|ocaml|oldlibs|otherosfs|perl|php|python|ruby|rust|science|shells|sound|tasks|tex|text|utils|vcs|video|web|x11|xfce|zope]
+Section: editors
+# 软件包优先级[required|important|stantard|optional|extra]
+Priority: optional
+# 软件包依赖
+Depends:
+# 软件包维护者(组织或个人)
+Maintainer: 尹作为 <[email protected]>
+# 软件包主页
+Homepage: https://gitee.com/cxasm/notepad--
+# 软件包建议
+Recommends:
+# 软件包描述信息
+Descrition: Notepad--是一个国产跨平台、简单的文本编辑器。
+ Notepad--是一个国产跨平台、简单的文本编辑器,是替换notepad++的一种选择。
+ 其内置强大的代码对比功能,让你丢掉付费的beyond compare。

+ 12 - 0
cmake/spark-desktop.desktop.in

@@ -0,0 +1,12 @@
+[Desktop Entry]
+Version=1.0
+Name=@APP_NAME@
+Name[zh_CN]=@APP_NAME_ZH_CN@
+Comment=@APP_COMMENT@
+Type=@APP_TYPE@
+Exec=@APP_EXECUTE_PATH@
+Icon=@APP_EXECUTE_ICON_PATH@
+Categories=@APP_CATEGORIES@
+MimeType=text/plain
+
+# Generated from the DesktopGenerater component of the z-Tools toolkit