| @@ -128,8 +128,3 @@ FORMS += \ | |||||
| src/ui/free_monitor_widget.ui \ | src/ui/free_monitor_widget.ui \ | ||||
| src/ui/runtime_monitor_window.ui \ | src/ui/runtime_monitor_window.ui \ | ||||
| src/ui/runtime_monitor_widget.ui | src/ui/runtime_monitor_widget.ui | ||||
| # 专用用户运行版打包时由脚本传入生成的工程资源;普通编程器构建不包含工程 | |||||
| !isEmpty(RUNTIME_PROJECT_RESOURCE) { | |||||
| RESOURCES += $$RUNTIME_PROJECT_RESOURCE | |||||
| } | |||||
| @@ -46,29 +46,10 @@ int main(int argc, char *argv[]) | |||||
| // 设置组织名称,用来区分这个程序保存的 Qt 配置 | // 设置组织名称,用来区分这个程序保存的 Qt 配置 | ||||
| application.setOrganizationName(QStringLiteral("QtProXinJe")); | application.setOrganizationName(QStringLiteral("QtProXinJe")); | ||||
| QString runtime_project_path; | |||||
| const QStringList arguments = application.arguments(); | |||||
| const int project_option = arguments.indexOf(QStringLiteral("--runtime-project")); | |||||
| if (project_option >= 0 && project_option + 1 < arguments.size()) | |||||
| { | |||||
| runtime_project_path = arguments.at(project_option + 1); | |||||
| } | |||||
| const QFileInfo executable_info(application.applicationFilePath()); | const QFileInfo executable_info(application.applicationFilePath()); | ||||
| const RuntimeProjectBundleLoadResult bundled_project_result = | const RuntimeProjectBundleLoadResult bundled_project_result = | ||||
| RuntimeProjectBundleService::load(executable_info.absoluteFilePath()); | RuntimeProjectBundleService::load(executable_info.absoluteFilePath()); | ||||
| const QString bundled_project = executable_info.absolutePath() | |||||
| + QStringLiteral("/runtime-project.json"); | |||||
| if (runtime_project_path.isEmpty() | |||||
| && executable_info.completeBaseName() != QStringLiteral("integrated_platform") | |||||
| && QFileInfo::exists(bundled_project)) | |||||
| { | |||||
| runtime_project_path = bundled_project; | |||||
| } | |||||
| const bool embedded_runtime_project = QFile::exists( | |||||
| QStringLiteral(":/runtime-project.json")); | |||||
| if (bundled_project_result.status == RuntimeProjectBundleStatus::Invalid | |||||
| && runtime_project_path.isEmpty() | |||||
| && !embedded_runtime_project) | |||||
| if (bundled_project_result.status == RuntimeProjectBundleStatus::Invalid) | |||||
| { | { | ||||
| QMessageBox::critical( | QMessageBox::critical( | ||||
| nullptr, | nullptr, | ||||
| @@ -78,9 +59,7 @@ int main(int argc, char *argv[]) | |||||
| } | } | ||||
| const bool bundled_runtime_project = bundled_project_result.status | const bool bundled_runtime_project = bundled_project_result.status | ||||
| == RuntimeProjectBundleStatus::Loaded; | == RuntimeProjectBundleStatus::Loaded; | ||||
| const bool user_runtime_mode = !runtime_project_path.isEmpty() | |||||
| || embedded_runtime_project | |||||
| || bundled_runtime_project; | |||||
| const bool user_runtime_mode = bundled_runtime_project; | |||||
| const ApplicationSettingsLoadResult application_settings = | const ApplicationSettingsLoadResult application_settings = | ||||
| ApplicationSettingsLoader::load( | ApplicationSettingsLoader::load( | ||||
| @@ -93,55 +72,25 @@ int main(int argc, char *argv[]) | |||||
| project_storage, application_settings.settings.projectLimits); | project_storage, application_settings.settings.projectLimits); | ||||
| if (user_runtime_mode) | if (user_runtime_mode) | ||||
| { | { | ||||
| ProjectOperationResult result; | |||||
| if (embedded_runtime_project && runtime_project_path.isEmpty()) | |||||
| { | |||||
| const QByteArray bytes = [] | |||||
| { | |||||
| QFile resource(QStringLiteral(":/runtime-project.json")); | |||||
| return resource.open(QIODevice::ReadOnly) | |||||
| ? resource.readAll() : QByteArray{}; | |||||
| }(); | |||||
| const QString temporary_path = QDir::tempPath() | |||||
| + QStringLiteral("/qtproxinje-runtime-project.json"); | |||||
| QFile temporary_file(temporary_path); | |||||
| if (bytes.isEmpty() || !temporary_file.open(QIODevice::WriteOnly) | |||||
| || temporary_file.write(bytes) != bytes.size()) | |||||
| { | |||||
| QMessageBox::critical( | |||||
| nullptr, | |||||
| QObject::tr("运行程序启动失败"), | |||||
| QObject::tr("无法读取内嵌项目资源")); | |||||
| return 2; | |||||
| } | |||||
| temporary_file.close(); | |||||
| result = project_service.load(temporary_path.toUtf8().toStdString()); | |||||
| QFile::remove(temporary_path); | |||||
| } | |||||
| else if (bundled_runtime_project && runtime_project_path.isEmpty()) | |||||
| const QString temporary_path = QDir::tempPath() | |||||
| + QStringLiteral("/qtproxinje-runtime-bundle-") | |||||
| + QString::number(application.applicationPid()) | |||||
| + QStringLiteral(".json"); | |||||
| QFile temporary_file(temporary_path); | |||||
| const QByteArray &bytes = bundled_project_result.project_data; | |||||
| if (bytes.isEmpty() || !temporary_file.open(QIODevice::WriteOnly) | |||||
| || temporary_file.write(bytes) != bytes.size()) | |||||
| { | { | ||||
| const QString temporary_path = QDir::tempPath() | |||||
| + QStringLiteral("/qtproxinje-runtime-bundle-project.json"); | |||||
| QFile temporary_file(temporary_path); | |||||
| const QByteArray &bytes = bundled_project_result.project_data; | |||||
| if (bytes.isEmpty() || !temporary_file.open(QIODevice::WriteOnly) | |||||
| || temporary_file.write(bytes) != bytes.size()) | |||||
| { | |||||
| QMessageBox::critical( | |||||
| nullptr, | |||||
| QObject::tr("运行程序启动失败"), | |||||
| QObject::tr("无法读取封装的工程资源")); | |||||
| return 2; | |||||
| } | |||||
| temporary_file.close(); | |||||
| result = project_service.load(temporary_path.toUtf8().toStdString()); | |||||
| QFile::remove(temporary_path); | |||||
| } | |||||
| else | |||||
| { | |||||
| result = project_service.load( | |||||
| runtime_project_path.toUtf8().toStdString()); | |||||
| QMessageBox::critical( | |||||
| nullptr, | |||||
| QObject::tr("运行程序启动失败"), | |||||
| QObject::tr("无法读取封装的工程资源")); | |||||
| return 2; | |||||
| } | } | ||||
| temporary_file.close(); | |||||
| const ProjectOperationResult result = project_service.load( | |||||
| temporary_path.toUtf8().toStdString()); | |||||
| QFile::remove(temporary_path); | |||||
| if (!result.succeeded) | if (!result.succeeded) | ||||
| { | { | ||||
| QMessageBox::critical( | QMessageBox::critical( | ||||
| @@ -1,7 +1,6 @@ | |||||
| [CmdletBinding()] | [CmdletBinding()] | ||||
| param( | param( | ||||
| [string]$OutputName = 'integrated_platform-win64', | |||||
| [string]$ProjectFile = '' | |||||
| [string]$OutputName = 'integrated_platform-win64' | |||||
| ) | ) | ||||
| Set-StrictMode -Version Latest | Set-StrictMode -Version Latest | ||||
| @@ -34,13 +33,6 @@ if ([string]::IsNullOrWhiteSpace($OutputName) -or | |||||
| throw "输出名称不是有效的 Windows 文件名:$OutputName" | throw "输出名称不是有效的 Windows 文件名:$OutputName" | ||||
| } | } | ||||
| if (-not [string]::IsNullOrWhiteSpace($ProjectFile)) { | |||||
| $resolvedProjectFile = [System.IO.Path]::GetFullPath($ProjectFile) | |||||
| if (-not (Test-Path -LiteralPath $resolvedProjectFile -PathType Leaf)) { | |||||
| throw "未找到运行版工程文件:$resolvedProjectFile" | |||||
| } | |||||
| } | |||||
| $packageDirectory = Join-Path $packageRoot $OutputName | $packageDirectory = Join-Path $packageRoot $OutputName | ||||
| $archivePath = Join-Path $packageRoot "$OutputName.zip" | $archivePath = Join-Path $packageRoot "$OutputName.zip" | ||||
| $resolvedProjectRoot = [System.IO.Path]::GetFullPath($projectRoot).TrimEnd('\') | $resolvedProjectRoot = [System.IO.Path]::GetFullPath($projectRoot).TrimEnd('\') | ||||
| @@ -54,22 +46,6 @@ if (-not $resolvedPackageRoot.StartsWith("$resolvedProjectRoot\build\", [System. | |||||
| New-Item -ItemType Directory -Path $buildDirectory -Force | Out-Null | New-Item -ItemType Directory -Path $buildDirectory -Force | Out-Null | ||||
| New-Item -ItemType Directory -Path $packageRoot -Force | Out-Null | New-Item -ItemType Directory -Path $packageRoot -Force | Out-Null | ||||
| $runtimeResourceFile = $null | |||||
| if (-not [string]::IsNullOrWhiteSpace($ProjectFile)) { | |||||
| $runtimeResourceFile = Join-Path $buildDirectory 'runtime_project.qrc' | |||||
| $escapedProjectPath = [System.Security.SecurityElement]::Escape($resolvedProjectFile) | |||||
| @( | |||||
| '<?xml version="1.0" encoding="UTF-8"?>' | |||||
| '<RCC><qresource prefix="/">' | |||||
| "<file alias=`"runtime-project.json`">$escapedProjectPath</file>" | |||||
| '</qresource></RCC>' | |||||
| ) | Set-Content -LiteralPath $runtimeResourceFile -Encoding UTF8 | |||||
| $resourceText = Get-Content -LiteralPath $runtimeResourceFile -Raw -Encoding UTF8 | |||||
| if (-not $resourceText.Contains($escapedProjectPath)) { | |||||
| throw "运行版资源未正确指向工程文件:$resolvedProjectFile" | |||||
| } | |||||
| } | |||||
| $originalPath = $env:Path | $originalPath = $env:Path | ||||
| $env:Path = "$qtRoot\bin;$mingwBin;$env:Path" | $env:Path = "$qtRoot\bin;$mingwBin;$env:Path" | ||||
| @@ -77,11 +53,7 @@ try { | |||||
| Push-Location $buildDirectory | Push-Location $buildDirectory | ||||
| try { | try { | ||||
| Write-Host 'RUNTIME_EXPORT_STAGE: qmake' | Write-Host 'RUNTIME_EXPORT_STAGE: qmake' | ||||
| $qmakeArguments = @($qtProjectFile, 'CONFIG+=release', 'CONFIG-=debug') | |||||
| if ($null -ne $runtimeResourceFile) { | |||||
| $qmakeArguments += "RUNTIME_PROJECT_RESOURCE=$($runtimeResourceFile.Replace('\', '/'))" | |||||
| } | |||||
| & $qmakePath @qmakeArguments | |||||
| & $qmakePath $qtProjectFile 'CONFIG+=release' 'CONFIG-=debug' | |||||
| if ($LASTEXITCODE -ne 0) { | if ($LASTEXITCODE -ne 0) { | ||||
| throw "qmake 执行失败,退出码:$LASTEXITCODE" | throw "qmake 执行失败,退出码:$LASTEXITCODE" | ||||
| } | } | ||||
| @@ -100,17 +72,6 @@ try { | |||||
| throw "未生成可执行文件:$executablePath" | throw "未生成可执行文件:$executablePath" | ||||
| } | } | ||||
| if ($null -ne $runtimeResourceFile) { | |||||
| $generatedResourceSource = Join-Path $buildDirectory 'release\qrc_runtime_project.cpp' | |||||
| if (-not (Test-Path -LiteralPath $generatedResourceSource)) { | |||||
| throw "未生成运行版工程资源:$generatedResourceSource" | |||||
| } | |||||
| $generatedResourceText = Get-Content -LiteralPath $generatedResourceSource -Raw -Encoding UTF8 | |||||
| if ($generatedResourceText -notlike '*runtime-project.json*') { | |||||
| throw '编译结果中缺少 runtime-project.json 资源' | |||||
| } | |||||
| } | |||||
| if (Test-Path -LiteralPath $packageDirectory) { | if (Test-Path -LiteralPath $packageDirectory) { | ||||
| Remove-Item -LiteralPath $packageDirectory -Recurse -Force | Remove-Item -LiteralPath $packageDirectory -Recurse -Force | ||||
| } | } | ||||
| @@ -120,12 +81,7 @@ try { | |||||
| Write-Host 'RUNTIME_EXPORT_STAGE: package' | Write-Host 'RUNTIME_EXPORT_STAGE: package' | ||||
| New-Item -ItemType Directory -Path $packageDirectory | Out-Null | New-Item -ItemType Directory -Path $packageDirectory | Out-Null | ||||
| $packagedExecutableName = if ([string]::IsNullOrWhiteSpace($ProjectFile)) { | |||||
| 'integrated_platform.exe' | |||||
| } else { | |||||
| "$OutputName.exe" | |||||
| } | |||||
| $packagedExecutable = Join-Path $packageDirectory $packagedExecutableName | |||||
| $packagedExecutable = Join-Path $packageDirectory 'integrated_platform.exe' | |||||
| Copy-Item -LiteralPath $executablePath -Destination $packagedExecutable | Copy-Item -LiteralPath $executablePath -Destination $packagedExecutable | ||||
| $runtimeFiles = @( | $runtimeFiles = @( | ||||
| 'Qt5Core.dll', 'Qt5Gui.dll', 'Qt5Network.dll', | 'Qt5Core.dll', 'Qt5Gui.dll', 'Qt5Network.dll', | ||||
| @@ -159,15 +115,11 @@ try { | |||||
| } | } | ||||
| } | } | ||||
| if ([string]::IsNullOrWhiteSpace($ProjectFile)) { | |||||
| Compress-Archive -LiteralPath $packageDirectory -DestinationPath $archivePath -CompressionLevel Optimal | |||||
| } | |||||
| Compress-Archive -LiteralPath $packageDirectory -DestinationPath $archivePath -CompressionLevel Optimal | |||||
| Write-Host "打包完成" | Write-Host "打包完成" | ||||
| Write-Host "运行目录:$packageDirectory" | Write-Host "运行目录:$packageDirectory" | ||||
| if ([string]::IsNullOrWhiteSpace($ProjectFile)) { | |||||
| Write-Host "压缩包:$archivePath" | |||||
| } | |||||
| Write-Host "压缩包:$archivePath" | |||||
| } | } | ||||
| finally { | finally { | ||||
| $env:Path = $originalPath | $env:Path = $originalPath | ||||