当前位置: 首页 > news >正文

搭建gitlab ci/cd runner实现对c++项目的自动编译和打包

        本文用于记录如何安装与配置gitlab runner并搭建c++项目的自动编译及打包的过程。

一、gitlab runner安装

        我要编译和打包的目标平台是windows平台,所以找了一台干净的windows主机,到gitlab官方网站下载了gitlab runner for windows的可执行文件,非常的简单,就一个可执行文件就够用了,放到一个剩余硬盘空间充足的盘符下面,创建个容易辨识的文件夹如gitlabrunner,把这个可执行文件放进去,然后准备安装为windows service和向gitlab 仓库进行注册,下面是它的命令行参数说明:

NAME:gitlab-runner-windows-amd64.exe - a GitLab RunnerUSAGE:gitlab-runner-windows-amd64.exe [global options] command [command options] [arguments...]VERSION:18.0.2 (4d7093e1)AUTHOR:GitLab Inc. <support@gitlab.com>COMMANDS:list                  List all configured runnersrun                   run multi runner serviceregister              register a new runnerreset-token           reset a runner's tokeninstall               install serviceuninstall             uninstall servicestart                 start servicestop                  stop servicerestart               restart servicestatus                get status of a servicerun-single            start single runnerunregister            unregister specific runnerverify                verify all registered runnerswrapper               start multi runner service wrapped with gRPC manager serverfleeting              manage fleeting pluginsartifacts-downloader  download and extract build artifacts (internal)artifacts-uploader    create and upload build artifacts (internal)cache-archiver        create and upload cache artifacts (internal)cache-extractor       download and extract cache artifacts (internal)cache-init            changed permissions for cache paths (internal)health-check          check health for a specific addressproxy-exec            execute internal commands (internal)read-logs             reads job logs from a file, used by kubernetes executor (internal)help, h               Shows a list of commands or help for one commandGLOBAL OPTIONS:--cpuprofile value           write cpu profile to file [%CPU_PROFILE%]--debug                      debug mode [%RUNNER_DEBUG%]--log-format value           Choose log format (options: runner, text, json) [%LOG_FORMAT%]--log-level value, -l value  Log level (options: debug, info, warn, error, fatal, panic) [%LOG_LEVEL%]--help, -h                   show help--version, -v                print the version

  执行gitlab-runner-windows-amd64.exe  install 就可以安装为windows服务了,然后再执行gitlab-runner-windows-amd64.exe register ,打开你的gitlab 仓库,找到仓库的“设置”-->“CI/CD”-->"RUNNER" ,点击展开,我这里的案例是这个gitlab runner只给我自己用,不打算给其他研发组使用,所以到“指定Runner”,复制“使用此网址注册Runner” 这里面的地址和注册令牌使用,然后为了和其他的gitlab runner进行区分,在输入tag标签的时候Enter tags for the runner (comma-separated):输入qt,windows-builder,注意这里面的多个标签是用逗号分割的,Enter an executor的时候输入shell,这就完事了,然后把服务启动起来sc.exe start gitlabrunner ,可以打开windows的服务去查看服务有没有正常启动,其实就算是正常启动了,后续因为要改动环境变量等还是需要在正式使用之前再次重启这个服务的。

二、搭建编译环境

        这里就简化记录,我是使用的vcpkg,正常安装visual studio 2022/vcpkg,这些并编译你要用到的c++库等。

三、编写gitlab ci/cd文件

        写这玩意耗费了2天的时间,太麻烦了,在项目的根目录创建.gitlab-ci.yml文件,以下内容有删减:

stages:- build- packagevariables:# Windows平台的vcpkg路径环境变量WINDOWS_VCPKG_ROOT: "C:\\vcpkg"WINDOWS_VCPKG_DEFAULT_TRIPLET: "x64-windows"# Windows Qt TOOLS BIN 路径配置 (for windeployqt and PATH)WINDOWS_QT_TOOLS_BIN: "C:\\vcpkg\\installed\\x64-windows\\tools\\qt5\\bin"# 构建配置BUILD_TYPE: "Release"# Windows平台构建任务
build_project_windows:stage: buildtags:- windows-builderrules:# 在master分支的所有提交上触发- if: $CI_COMMIT_BRANCH == "master"when: always# 在其他分支的推送时也触发- if: $CI_PIPELINE_SOURCE == "push"when: always# 手动触发- when: manualallow_failure: truebefore_script:- echo "Setting up Windows environment variables"- $env:VCPKG_ROOT = $env:WINDOWS_VCPKG_ROOT- $env:QT_BIN_DIR = $env:WINDOWS_QT_TOOLS_BIN- $env:PATH += ";$env:VCPKG_ROOT;$env:QT_BIN_DIR"- $env:CMAKE_TOOLCHAIN_FILE = "$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake"- echo "Verifying environment"- echo "Building on Windows platform"- 'echo "VCPKG_ROOT: $env:VCPKG_ROOT"'- 'echo "QT_BIN_DIR (for deploy): $env:QT_BIN_DIR"'- echo "Creating build directory"- if (!(Test-Path "build-windows")) { New-Item -ItemType Directory -Path "build-windows" }script:- 'echo "Step 3: Configuring CMake project"'- echo "Configuring CMake project for Windows..."- cd build-windows- echo "CMake configuration parameters:"- 'echo "  VCPKG_ROOT: $env:VCPKG_ROOT"'- 'echo "  QT_BIN_DIR (for deploy): $env:QT_BIN_DIR"'- >cmake .. -G "Visual Studio 17 2022" -A x64-DCMAKE_BUILD_TYPE=$env:BUILD_TYPE-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake"-DVCPKG_TARGET_TRIPLET=x64-windows-DUSE_VCPKG=ON- 'echo "Step 4: Building main project"'- echo "Building main project for Windows..."- cmake --build . --config $env:BUILD_TYPE --parallel- 'echo "Step 5: Deploying Qt dependencies"'- 'echo "Deploying Qt dependencies using windeployqt..."'- '$targetDir = "./$env:BUILD_TYPE"'- 'echo "Target directory is ${targetDir}"'- 'echo "Current working directory is $(Get-Location)"'- 'echo "Listing contents of current directory:"'- dir- 'echo "Listing contents of target directory:"'- 'if (Test-Path $targetDir) { dir $targetDir } else { echo "Target directory does not exist" }'- 'echo "Checking for exe files in target directory:"'- 'if (Test-Path "${targetDir}/*.exe") { dir "${targetDir}/*.exe" } else { echo "No exe files found in ${targetDir}" }'- '$windeployqt = "$env:QT_BIN_DIR/windeployqt.exe"'- 'echo "windeployqt path is ${windeployqt}"'- |if (Test-Path $windeployqt) {echo "Found windeployqt, checking for exe files..."$exeFiles = Get-ChildItem -Path $targetDir -Filter "*.exe" -ErrorAction SilentlyContinueif ($exeFiles.Count -gt 0) {echo "Found exe files, running windeployqt..."foreach ($exe in $exeFiles) {echo "Deploying Qt dependencies for $($exe.FullName)"& $windeployqt --release --no-system-d3d-compiler --no-opengl-sw --no-angle $exe.FullName}} else {echo "ERROR No exe files found in ${targetDir}"echo "Contents of ${targetDir}:"if (Test-Path $targetDir) { dir $targetDir } else { echo "Directory does not exist" }}} else {echo "windeployqt not found at ${windeployqt}, copying Qt DLLs manually..."# 确保目标目录存在if (!(Test-Path $targetDir)) {echo "Creating target directory ${targetDir}"New-Item -ItemType Directory -Path $targetDir -Force}# vcpkg的Release DLLs可能直接在installed/x64-windows/bin下$qtDllPath = "$env:QT_BIN_DIR"# 如果tools/qt5/bin下没有DLL,尝试vcpkg的bin目录if (!(Test-Path "$qtDllPath/Qt5Core.dll")) {$qtDllPath = "$env:VCPKG_ROOT/installed/x64-windows/bin"echo "Trying alternative Qt DLL path ${qtDllPath}"}if (Test-Path $qtDllPath) {echo "Copying Qt DLLs from ${qtDllPath}"Copy-Item "$qtDllPath/Qt5Core.dll" -Destination $targetDir -ErrorAction SilentlyContinue -ForceCopy-Item "$qtDllPath/Qt5Gui.dll" -Destination $targetDir -ErrorAction SilentlyContinue -ForceCopy-Item "$qtDllPath/Qt5Widgets.dll" -Destination $targetDir -ErrorAction SilentlyContinue -ForceCopy-Item "$qtDllPath/Qt5Network.dll" -Destination $targetDir -ErrorAction SilentlyContinue -ForceCopy-Item "$qtDllPath/Qt5SerialPort.dll" -Destination $targetDir -ErrorAction SilentlyContinue -ForceCopy-Item "$qtDllPath/Qt5Sql.dll" -Destination $targetDir -ErrorAction SilentlyContinue -ForceCopy-Item "$qtDllPath/Qt5Svg.dll" -Destination $targetDir -ErrorAction SilentlyContinue -ForceCopy-Item "$qtDllPath/Qt5Concurrent.dll" -Destination $targetDir -ErrorAction SilentlyContinue -Force} else {echo "ERROR Qt DLL path not found ${qtDllPath}"}}- 'echo "Step 7: Copying Visual C++ runtime"'- 'echo "Copying Visual C++ runtime..."'- '$vcRedistPath = "C:/Program Files (x86)/Microsoft Visual Studio/2022/Enterprise/VC/Redist/MSVC/14.37.32822/x64/Microsoft.VC143.CRT"'- |if (Test-Path $vcRedistPath) {Copy-Item "$vcRedistPath/*.dll" -Destination $targetDir -Force} else {echo "Warning VC Redist path not found ${vcRedistPath}"}- 'echo "Final verification of build artifacts..."'- 'echo "Contents of Release directory:"'- 'if (Test-Path $targetDir) { dir $targetDir } else { echo "Release directory not found" }'- 'echo "Checking for devicelib.dll in Release directory:"'- 'if (Test-Path "${targetDir}/devicelib.dll") { echo "devicelib.dll found in Release directory" } else { echo "devicelib.dll NOT found in Release directory" }'- cd ..artifacts:name: "windows-build-$CI_COMMIT_SHORT_SHA"paths:- build-windows/Release/- build-windows/*.dllexpire_in: 1 hour# Windows平台打包任务
package_installer_windows:stage: packagetags:- windows-builderrules:# 在master分支且构建成功后触发- if: $CI_COMMIT_BRANCH == "master"when: on_success# 在其他分支推送且构建成功后触发- if: $CI_PIPELINE_SOURCE == "push"when: on_successdependencies:- build_project_windowsscript:- echo "Creating Windows installer package..."- echo "Checking for NSIS..."- |if (Get-Command "makensis" -ErrorAction SilentlyContinue) {echo "Found NSIS, creating installer..."echo "Current directory: $(Get-Location)"echo "Listing installer files:"dir *.nsi -ErrorAction SilentlyContinueif (Test-Path "installer.nsi") {echo "Building NSIS installer..."makensis installer.nsiecho "Installer creation completed"dir *.exe -ErrorAction SilentlyContinue} else {echo "ERROR: installer.nsi not found"dir}} else {echo "ERROR: NSIS (makensis) not found in PATH"echo "Available commands:"Get-Command make* -ErrorAction SilentlyContinue}- echo "Creating ZIP package as backup..."- $zipName = "xxxx-Windows-x64-$env:CI_COMMIT_SHORT_SHA.zip"- Compress-Archive -Path "build-windows/Release/*" -DestinationPath $zipName -Force- echo "Package creation completed"artifacts:name: "windows-installer-$CI_COMMIT_SHORT_SHA"paths:- "*.exe" # Windows安装程序- "*Windows*.zip" # Windows ZIP包expire_in: 1 week# 为将来的Linux构建预留模板
.linux_build_template: &linux_build_templatestage: buildbefore_script:- echo "Building on Linux platform"- export VCPKG_ROOT="/opt/vcpkg"- export QT_DIR="/opt/Qt/5.15.2/gcc_64"- export PATH="$VCPKG_ROOT:$QT_DIR/bin:$PATH"- mkdir -p build-linuxscript:- echo "Linux build steps will be implemented here"artifacts:name: "linux-build-$CI_COMMIT_SHORT_SHA"paths:- build-linux/expire_in: 1 hour# 示例:Ubuntu构建任务(暂时禁用)
build_project_ubuntu:<<: *linux_build_templatetags:- linux- ubunturules:- if: "$CI_RUNNER_TAGS =~ /ubuntu/"when: manual # 手动触发,直到配置完成script:- echo "Ubuntu build not yet implemented"

  上面的策略是只要提交代码就自动编译,其实应该是tag版本的时候才触发编译。

  下面是我的cmakelists.txt里面的部分内容:

cmake_minimum_required(VERSION 3.16)project(xxxx VERSION 1.0.0 LANGUAGES CXX)# 添加选项用于切换环境
option(USE_VCPKG "Use vcpkg instead of MSYS2 MinGW64" OFF)# 定义路径变量,便于维护
if(WIN32)# Windows平台路径if(USE_VCPKG)# 优先使用环境变量,如果没有则使用默认值if(DEFINED ENV{VCPKG_ROOT})set(VCPKG_ROOT_DIR "$ENV{VCPKG_ROOT}")message(STATUS "Using VCPKG_ROOT from environment: ${VCPKG_ROOT_DIR}")elseif(DEFINED VCPKG_ROOT_DIR)# 使用CMake命令行传入的值message(STATUS "Using VCPKG_ROOT from CMake variable: ${VCPKG_ROOT_DIR}")else()# 默认路径set(VCPKG_ROOT_DIR "D:/vcpkg/vcpkg")message(STATUS "Using default VCPKG_ROOT: ${VCPKG_ROOT_DIR}")endif()# 设置vcpkg相关路径set(VCPKG_INSTALLED_DIR "${VCPKG_ROOT_DIR}/installed/x64-windows")message(STATUS "Forcing VCPKG_INSTALLED_DIR to: ${VCPKG_INSTALLED_DIR}")        set(VCPKG_TOOLS_DIR "${VCPKG_INSTALLED_DIR}/tools/qt5")set(VCPKG_SCRIPTS_DIR "${VCPKG_ROOT_DIR}/scripts")endif()# MSYS2路径设置set(MSYS2_ROOT_DIR "D:/msys64")set(MSYS2_MINGW64_DIR "${MSYS2_ROOT_DIR}/mingw64")set(MSYS2_USR_DIR "${MSYS2_ROOT_DIR}/usr")
endif()if(UNIX)# UNIX平台路径set(VCPKG_ROOT_DIR "/data/cpp/vcpkg")set(VCPKG_SCRIPTS_DIR "${VCPKG_ROOT_DIR}/scripts")# 检测系统架构execute_process(COMMAND uname -mOUTPUT_VARIABLE SYSTEM_ARCHOUTPUT_STRIP_TRAILING_WHITESPACE)# 根据检测到的架构设置对应的目录if(SYSTEM_ARCH STREQUAL "x86_64")set(VCPKG_TRIPLET "x64-linux")elseif(SYSTEM_ARCH STREQUAL "i686")set(VCPKG_TRIPLET "x86-linux")elseif(SYSTEM_ARCH STREQUAL "aarch64")set(VCPKG_TRIPLET "arm64-linux")elseif(SYSTEM_ARCH STREQUAL "armv7l")set(VCPKG_TRIPLET "arm-linux")elseif(SYSTEM_ARCH STREQUAL "loongarch64")set(VCPKG_TRIPLET "loongarch64-linux")else()# 默认使用x64-linuxmessage(WARNING "未知架构: ${SYSTEM_ARCH},使用默认的x64-linux triplet")set(VCPKG_TRIPLET "x64-linux")endif()# 设置安装目录路径set(VCPKG_INSTALLED_DIR "${VCPKG_ROOT_DIR}/installed/${VCPKG_TRIPLET}")set(VCPKG_TOOLS_DIR "${VCPKG_INSTALLED_DIR}/tools/qt5")set(VCPKG_SCRIPTS_DIR "${VCPKG_ROOT_DIR}/scripts")message(STATUS "使用VCPKG triplet: ${VCPKG_TRIPLET}")
endif()message(STATUS "VCPKG_INSTALLED_DIR: ${VCPKG_INSTALLED_DIR}")
message(STATUS "VCPKG_TOOLS_DIR: ${VCPKG_TOOLS_DIR}")
message(STATUS "VCPKG_SCRIPTS_DIR: ${VCPKG_SCRIPTS_DIR}")# 设置C++标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)set(QUAZIP_QT_MAJOR_VERSION 5) 
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build static libraries" FORCE)
set(QUAZIP_BZIP2 OFF CACHE BOOL "Disable BZIP2 compression" FORCE)
set(QUAZIP_USE_QT_ZLIB OFF CACHE BOOL "Use Qt ZLIB" FORCE)

     gitlab ci/cd文件里面指定了编译的时候设置      -DUSE_VCPKG=ON ,然后yml里面在  before_script:的部分设置了VCPKG的环境变量值。

      最后是打包脚本installer.nsi的内容:

# xxxx NSIS 安装脚本
# 编码: UTF-8!define PRODUCT_NAME "xxxxx"
!define PRODUCT_VERSION "1.0.0"
!define PRODUCT_PUBLISHER "xxxx Technology"
!define PRODUCT_WEB_SITE "https://www.xxxxx"
!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\xxxxx.exe"
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
!define PRODUCT_UNINST_ROOT_KEY "HKLM"
!define PRODUCT_STARTMENU_REGVAL "NSIS:StartMenuDir"# 设置安装程序属性
Name "${PRODUCT_NAME}"
OutFile "xxx-Setup.exe"
InstallDir "$PROGRAMFILES\xxxx"
InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""
ShowInstDetails show
ShowUnInstDetails show
RequestExecutionLevel admin
Unicode True# 现代UI设置
!include "MUI2.nsh"
!include "FileFunc.nsh"
!include "LogicLib.nsh"
!include "nsProcess.nsh"# UI配置
!define MUI_ABORTWARNING
!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico"
!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"# 安装页面
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_DIRECTORY# 开始菜单页面
Var StartMenuFolder
!define MUI_STARTMENUPAGE_DEFAULTFOLDER "${PRODUCT_NAME}"
!define MUI_STARTMENUPAGE_REGISTRY_ROOT "${PRODUCT_UNINST_ROOT_KEY}"
!define MUI_STARTMENUPAGE_REGISTRY_KEY "${PRODUCT_UNINST_KEY}"
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${PRODUCT_STARTMENU_REGVAL}"
!insertmacro MUI_PAGE_STARTMENU Application $StartMenuFolder!insertmacro MUI_PAGE_INSTFILES# 完成页面
!define MUI_FINISHPAGE_RUN "$INSTDIR\xxxx.exe"
!define MUI_FINISHPAGE_RUN_TEXT "立即启动xxxx"
!define MUI_FINISHPAGE_SHOWREADME ""
!define MUI_FINISHPAGE_SHOWREADME_TEXT "开机自动启动"
!define MUI_FINISHPAGE_SHOWREADME_FUNCTION EnableAutoStart
!insertmacro MUI_PAGE_FINISH# 卸载页面
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES# 语言文件
!insertmacro MUI_LANGUAGE "SimpChinese"# 版本信息
VIProductVersion "1.0.0.0"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "ProductName" "${PRODUCT_NAME}"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "Comments" "xxxxx"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "CompanyName" "${PRODUCT_PUBLISHER}"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "LegalTrademarks" "${PRODUCT_NAME} 是 ${PRODUCT_PUBLISHER} 的商标"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "LegalCopyright" "© ${PRODUCT_PUBLISHER}"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "FileDescription" "${PRODUCT_NAME}"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "FileVersion" "${PRODUCT_VERSION}"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "ProductVersion" "${PRODUCT_VERSION}"# 检查进程函数
Function CheckAndKillProcessStrCpy $1 "xxxx.exe"nsProcess::_FindProcess "$1"Pop $R0${If} $R0 = 0MessageBox MB_YESNO|MB_ICONQUESTION "检测到xxxx正在运行,需要关闭才能继续安装。是否立即关闭?" IDYES KillProcess IDNO AbortInstallKillProcess:DetailPrint "正在关闭xxxx..."nsProcess::_KillProcess "$1"Pop $R0Sleep 2000# 再次检查进程是否已关闭nsProcess::_FindProcess "$1"Pop $R0${If} $R0 = 0MessageBox MB_OK|MB_ICONSTOP "无法关闭xxxx,请手动关闭后重新运行安装程序。"Abort${EndIf}DetailPrint "xxxx已关闭"Goto ContinueInstallAbortInstall:AbortContinueInstall:${EndIf}
FunctionEnd# 开机自动启动函数
Function EnableAutoStartWriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Run" "${PRODUCT_NAME}" "$INSTDIR\xxxx.exe"DetailPrint "已设置开机自动启动"
FunctionEnd# 安装程序初始化
Function .onInit# 检查管理员权限UserInfo::GetAccountTypepop $0${If} $0 != "admin"MessageBox MB_ICONSTOP "此程序需要管理员权限才能安装,请右键选择$\"以管理员身份运行$\"。"SetErrorLevel 740 # ERROR_ELEVATION_REQUIREDQuit${EndIf}# 检查并关闭正在运行的进程Call CheckAndKillProcess
FunctionEndSection "主程序" SEC01SetOutPath "$INSTDIR"SetOverwrite on# 复制启动器程序(主入口)File "build-windows\Release\xxxx.exe"# 复制主程序文件File "build-windows\Release\xxxx.exe"# 复制动态库File "build-windows\Release\xxxx.dll"# 复制Qt依赖库File "build-windows\Release\*.dll"# 复制Qt平台插件SetOutPath "$INSTDIR\platforms"File /nonfatal "build-windows\Release\platforms\*.*"# 复制Qt翻译文件SetOutPath "$INSTDIR\translations"File /nonfatal "build-windows\Release\translations\*.*"# 复制Qt网络插件SetOutPath "$INSTDIR\bearer"File /nonfatal "build-windows\Release\bearer\*.*"# 复制Qt图像格式插件SetOutPath "$INSTDIR\imageformats"File /nonfatal "build-windows\Release\imageformats\*.*"# 复制Qt图标引擎插件SetOutPath "$INSTDIR\iconengines"File /nonfatal "build-windows\Release\iconengines\*.*"# 复制Qt样式插件SetOutPath "$INSTDIR\styles"File /nonfatal "build-windows\Release\styles\*.*"# 复制Qt通用插件目录SetOutPath "$INSTDIR\plugins"File /nonfatal /r "build-windows\Release\plugins\*.*"# 复制Qt SQL驱动插件SetOutPath "$INSTDIR\sqldrivers"File /nonfatal "build-windows\Release\sqldrivers\*.*"# 回到主目录SetOutPath "$INSTDIR"# 创建卸载程序WriteUninstaller "$INSTDIR\uninst.exe"
SectionEndSection "开始菜单快捷方式" SEC02!insertmacro MUI_STARTMENU_WRITE_BEGIN ApplicationCreateDirectory "$SMPROGRAMS\$StartMenuFolder"CreateShortCut "$SMPROGRAMS\$StartMenuFolder\${PRODUCT_NAME}.lnk" "$INSTDIR\xxxxx.exe"CreateShortCut "$SMPROGRAMS\$StartMenuFolder\卸载${PRODUCT_NAME}.lnk" "$INSTDIR\uninst.exe"!insertmacro MUI_STARTMENU_WRITE_END
SectionEndSection "桌面快捷方式" SEC03CreateShortCut "$DESKTOP\${PRODUCT_NAME}.lnk" "$INSTDIR\xxxx.exe"
SectionEndSection -AdditionalIconsWriteIniStr "$INSTDIR\${PRODUCT_NAME}.url" "InternetShortcut" "URL" "${PRODUCT_WEB_SITE}"!insertmacro MUI_STARTMENU_WRITE_BEGIN ApplicationCreateShortCut "$SMPROGRAMS\$StartMenuFolder\Website.lnk" "$INSTDIR\${PRODUCT_NAME}.url"!insertmacro MUI_STARTMENU_WRITE_END
SectionEndSection -PostWriteUninstaller "$INSTDIR\uninst.exe"WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\launch.exe"WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\launch.exe"WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"# 获取安装大小${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2IntFmt $0 "0x%08X" $0WriteRegDWORD ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "EstimatedSize" "$0"
SectionEnd# 卸载程序初始化
Function un.onInitMessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "您确实要完全移除 $(^Name) 及其所有的组件?" IDYES +2Abort# 检查并关闭正在运行的进程StrCpy $1 "xxxx.exe"nsProcess::_FindProcess "$1"Pop $R0${If} $R0 = 0MessageBox MB_YESNO|MB_ICONQUESTION "检测到设备采集服务正在运行,需要关闭才能继续卸载。是否立即关闭?" IDYES KillProcess IDNO AbortUninstallKillProcess:DetailPrint "正在关闭设备采集服务..."nsProcess::_KillProcess "$1"Pop $R0Sleep 2000Goto ContinueUninstallAbortUninstall:AbortContinueUninstall:${EndIf}
FunctionEndFunction un.onUninstSuccessHideWindowMessageBox MB_ICONINFORMATION|MB_OK "$(^Name) 已成功地从您的计算机中移除。"
FunctionEndSection Uninstall# 删除开机自动启动DeleteRegValue HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Run" "${PRODUCT_NAME}"# 删除文件Delete "$INSTDIR\${PRODUCT_NAME}.url"Delete "$INSTDIR\uninst.exe"Delete "$INSTDIR\xxx.exe"Delete "$INSTDIR\xxxx.exe"Delete "$INSTDIR\xxx.dll"Delete "$INSTDIR\*.dll"# 删除Qt插件目录RMDir /r "$INSTDIR\platforms"RMDir /r "$INSTDIR\translations"RMDir /r "$INSTDIR\bearer"RMDir /r "$INSTDIR\imageformats"RMDir /r "$INSTDIR\iconengines"RMDir /r "$INSTDIR\styles"RMDir /r "$INSTDIR\plugins"RMDir /r "$INSTDIR\sqldrivers"# 删除快捷方式!insertmacro MUI_STARTMENU_GETFOLDER "Application" $StartMenuFolderDelete "$SMPROGRAMS\$StartMenuFolder\卸载${PRODUCT_NAME}.lnk"Delete "$SMPROGRAMS\$StartMenuFolder\Website.lnk"Delete "$SMPROGRAMS\$StartMenuFolder\${PRODUCT_NAME}.lnk"RMDir "$SMPROGRAMS\$StartMenuFolder"Delete "$DESKTOP\${PRODUCT_NAME}.lnk"RMDir "$INSTDIR"DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}"SetAutoClose true
SectionEnd

   至此,你只要push代码到gitlab仓库以后就可以自动按照Release方式编译你的程序及自动调用nsis编译你的打包脚本得到安装程序了。

http://www.xdnf.cn/news/962659.html

相关文章:

  • 51c嵌入式※~电路~合集32~PWM
  • 入门机器学习需要的统计基础
  • ArcGIS+AI:涵盖AI大模型应用、ArcGIS功能详解、Prompt技巧、AI助力的数据处理、空间分析、遥感分析、二次开发及综合应用等
  • 置信水平、置信区间
  • ArcGIS土地利用数据制备、分析及基于FLUS模型土地利用预测技术应用
  • 在Windows上搭建Kubernetes集群
  • 渗透靶场PortSwigger Labs指南:规范链接的反射XSS
  • Docker监控服务部署
  • 如何提升企微CRM系统数据的准确性?5大核心策略详解
  • 鹰盾加密器基于AI的视频个性化压缩技术深度解析:从智能分析到无损压缩实践
  • 鹰盾加密器的超混沌加密原理深度解析:从理论基础到视频应用
  • AWS WebRTC 使用SDK-C demo 实现master推流和viewer拉流
  • 后进先出(LIFO)详解
  • [科研理论]无人机底层控制算法PID、LQR、MPC解析
  • 土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测技术应用
  • OOM模拟排查过程记录
  • 火山引擎大模型系列可以用来作什么
  • TDengine 快速体验(云服务方式)
  • ceph集群调整pg数量实战(上)
  • TikTok矩阵养号实战:住宅IP纯净度与设备指纹联动方案
  • 空间注意力机制
  • uniapp开发小程序vendor.js 过大
  • 使用java实现蒙特卡洛模拟风险预测功能
  • AI一周事件(2025年6月3日-6月9日)
  • WHAT - 组件库单入口打包和多入口打包
  • “液态玻璃”难解苹果AI焦虑:WWDC25背后的信任危机
  • 自动化三维扫描检测赋能汽车铸造件高效检测
  • 笔记 操作系统复习
  • 供应链管理-物流:自动驾驶分为几个级别/L0无自动化/L1驾驶辅助/L2部分自动化/L3有条件自动化/L4高度自动化/L5完全自动化
  • 云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?