Generate version files and integrate into build
Add CMake configure steps to produce version.h and version.sh from templates and include the build dir for the generated header. Add version.h.in and version.sh.in, include version.h in VulkanWidget and use APP_VK_VERSION for the Vulkan applicationVersion. Update make_deb.sh to source version.sh for the package version instead
This commit is contained in:
parent
3c52aa1ca3
commit
ad3524bd23
|
|
@ -123,6 +123,20 @@ else()
|
|||
message(STATUS "Vulkan support disabled")
|
||||
endif()
|
||||
|
||||
# Generate version header from template (for C++ code)
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/version.h.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/version.h"
|
||||
@ONLY
|
||||
)
|
||||
|
||||
# Generate version shell script from template (for shell scripts)
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/version.sh.in"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/version.sh"
|
||||
@ONLY
|
||||
)
|
||||
|
||||
# Common source files
|
||||
set(SOURCES
|
||||
src/main.cpp
|
||||
|
|
@ -187,6 +201,11 @@ add_executable(${PROJECT_NAME}
|
|||
${HEADERS}
|
||||
)
|
||||
|
||||
# Include build directory for generated version.h
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
# Link Qt5 libraries
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
Qt5::Core
|
||||
|
|
|
|||
21
make_deb.sh
21
make_deb.sh
|
|
@ -12,13 +12,24 @@ NC='\033[0m' # No Color
|
|||
# 配置变量
|
||||
APP_NAME="ScreenLockDetector"
|
||||
PACKAGE_NAME="ScreenLockDetector"
|
||||
# 从 CMakeLists.txt 中提取版本号
|
||||
VERSION=$(grep -oP '(?<=project\(ScreenLockDetector VERSION )[0-9.]+' CMakeLists.txt)
|
||||
if [ -z "$VERSION" ]; then
|
||||
echo -e "${RED}错误: 无法从 CMakeLists.txt 中提取版本号${NC}"
|
||||
|
||||
# 从自动生成的 version.sh 中读取版本号
|
||||
if [ ! -f "version.sh" ]; then
|
||||
echo -e "${RED}错误: version.sh 文件不存在${NC}"
|
||||
echo -e "${YELLOW}请先运行 ./build.sh 生成版本文件${NC}"
|
||||
exit 1
|
||||
fi
|
||||
echo -e "${GREEN}✓ 从 CMakeLists.txt 读取版本号: ${VERSION}${NC}"
|
||||
|
||||
# Source version.sh to get APP_VERSION
|
||||
source version.sh
|
||||
|
||||
if [ -z "$APP_VERSION" ]; then
|
||||
echo -e "${RED}错误: 无法从 version.sh 中读取版本号${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
VERSION="$APP_VERSION"
|
||||
echo -e "${GREEN}✓ 从 version.sh 读取版本号: ${VERSION}${NC}"
|
||||
ARCH="amd64"
|
||||
QT_DIR="$HOME/sdk/qt-5.15.2"
|
||||
LINUXDEPLOYQT="${LINUXDEPLOYQT:-$HOME/tools/sunvpack-py/bin/linuxdeployqt}"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef VERSION_H
|
||||
#define VERSION_H
|
||||
|
||||
// Auto-generated version information from CMakeLists.txt
|
||||
// DO NOT EDIT THIS FILE MANUALLY - Edit CMakeLists.txt instead
|
||||
|
||||
#define APP_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
|
||||
#define APP_VERSION_MINOR @PROJECT_VERSION_MINOR@
|
||||
#define APP_VERSION_PATCH @PROJECT_VERSION_PATCH@
|
||||
#define APP_VERSION_STRING "@PROJECT_VERSION@"
|
||||
|
||||
// Vulkan version macros
|
||||
#define APP_VK_VERSION VK_MAKE_VERSION(APP_VERSION_MAJOR, APP_VERSION_MINOR, APP_VERSION_PATCH)
|
||||
|
||||
#endif // VERSION_H
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
#include "vulkanwidget.h"
|
||||
#include "vulkanrenderer.h"
|
||||
#include "version.h"
|
||||
#include <QDebug>
|
||||
#include <QShowEvent>
|
||||
#include <QHideEvent>
|
||||
|
|
@ -68,7 +69,7 @@ VulkanWidget::VulkanWidget(QWidget *parent)
|
|||
// Create render timer
|
||||
m_renderTimer = new QTimer(this);
|
||||
connect(m_renderTimer, &QTimer::timeout, this, &VulkanWidget::onRenderTimer);
|
||||
|
||||
|
||||
// Initialize FPS calculation
|
||||
m_frameTimes.reserve(FPS_SAMPLE_COUNT);
|
||||
|
||||
|
|
@ -111,7 +112,7 @@ void VulkanWidget::setRenderingEnabled(bool enabled)
|
|||
|
||||
if (m_renderingEnabled) {
|
||||
qDebug() << "Vulkan rendering ENABLED - Resuming animations";
|
||||
|
||||
|
||||
// Check if device was lost (e.g., after wake from sleep)
|
||||
if (m_deviceLost) {
|
||||
qDebug() << "Device lost detected on resume, attempting recovery...";
|
||||
|
|
@ -121,7 +122,7 @@ void VulkanWidget::setRenderingEnabled(bool enabled)
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 恢复渲染时,重新启动定时器(锁屏时已停止)
|
||||
if (!m_renderTimer->isActive()) {
|
||||
m_renderTimer->start(16); // ~60 FPS
|
||||
|
|
@ -291,7 +292,7 @@ bool VulkanWidget::createInstance()
|
|||
VkApplicationInfo appInfo = {};
|
||||
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||
appInfo.pApplicationName = "VulkanWidget";
|
||||
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
|
||||
appInfo.applicationVersion = APP_VK_VERSION; // Auto-generated from CMakeLists.txt
|
||||
appInfo.pEngineName = "No Engine";
|
||||
appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
|
||||
appInfo.apiVersion = VK_API_VERSION_1_0;
|
||||
|
|
@ -344,7 +345,7 @@ bool VulkanWidget::createSurface()
|
|||
#elif defined(__linux__)
|
||||
VkXlibSurfaceCreateInfoKHR createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
|
||||
|
||||
|
||||
// Reuse existing X11 display or open a new one
|
||||
Display* x11Display = static_cast<Display*>(m_x11Display);
|
||||
if (!x11Display) {
|
||||
|
|
@ -358,7 +359,7 @@ bool VulkanWidget::createSurface()
|
|||
} else {
|
||||
qDebug() << "Reusing existing X11 display";
|
||||
}
|
||||
|
||||
|
||||
createInfo.dpy = x11Display;
|
||||
createInfo.window = static_cast<Window>(window->winId());
|
||||
|
||||
|
|
@ -772,7 +773,7 @@ void VulkanWidget::renderFrame()
|
|||
if (!m_initialized || m_isClosing) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Don't render if device is lost (recovery will be attempted on next enable)
|
||||
if (m_deviceLost) {
|
||||
return;
|
||||
|
|
@ -785,14 +786,14 @@ void VulkanWidget::renderFrame()
|
|||
QDateTime currentTime = QDateTime::currentDateTime();
|
||||
qint64 frameTimeUs = m_lastFrameTime.msecsTo(currentTime) * 1000; // Convert to microseconds
|
||||
m_lastFrameTime = currentTime;
|
||||
|
||||
|
||||
if (frameTimeUs > 0) {
|
||||
// Add frame time to circular buffer
|
||||
if (m_frameTimes.size() >= FPS_SAMPLE_COUNT) {
|
||||
m_frameTimes.erase(m_frameTimes.begin());
|
||||
}
|
||||
m_frameTimes.push_back(frameTimeUs);
|
||||
|
||||
|
||||
// Calculate average FPS from recent frames
|
||||
if (!m_frameTimes.empty()) {
|
||||
qint64 totalTimeUs = 0;
|
||||
|
|
@ -857,7 +858,7 @@ void VulkanWidget::renderFrame()
|
|||
result = vkQueueSubmit(m_queue, 1, &submitInfo, m_inFlightFences[m_currentFrame]);
|
||||
if (result != VK_SUCCESS) {
|
||||
qDebug() << "Failed to submit draw command buffer! Error code = " << result;
|
||||
|
||||
|
||||
// Handle device lost error (e.g., after wake from sleep/hibernation)
|
||||
if (result == VK_ERROR_DEVICE_LOST || result == -4) {
|
||||
qDebug() << "VK_ERROR_DEVICE_LOST detected! Attempting to recover device...";
|
||||
|
|
@ -957,7 +958,7 @@ void VulkanWidget::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t i
|
|||
// Calculate elapsed time in seconds
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
qint64 elapsedTime = m_startTime.secsTo(now);
|
||||
|
||||
|
||||
m_renderer->recordCommandBuffer(commandBuffer, imageIndex, imageView,
|
||||
m_frameCount, static_cast<double>(elapsedTime),
|
||||
m_currentFps,
|
||||
|
|
@ -1083,7 +1084,7 @@ void VulkanWidget::cleanupVulkan()
|
|||
if (m_surface != VK_NULL_HANDLE) {
|
||||
vkDestroySurfaceKHR(m_instance, m_surface, nullptr);
|
||||
}
|
||||
|
||||
|
||||
// Close X11 display if it was opened (Linux only)
|
||||
#ifdef __linux__
|
||||
if (m_x11Display) {
|
||||
|
|
@ -1228,13 +1229,13 @@ std::vector<const char*> VulkanWidget::getRequiredDeviceExtensions()
|
|||
bool VulkanWidget::handleDeviceLost()
|
||||
{
|
||||
qDebug() << "=== Handling device lost error ===";
|
||||
|
||||
|
||||
// Stop rendering timer to prevent more render attempts during recovery
|
||||
if (m_renderTimer && m_renderTimer->isActive()) {
|
||||
m_renderTimer->stop();
|
||||
qDebug() << "Render timer stopped for device recovery";
|
||||
}
|
||||
|
||||
|
||||
// Wait for any pending operations to complete (may fail, but try anyway)
|
||||
if (m_device != VK_NULL_HANDLE) {
|
||||
VkResult result = vkDeviceWaitIdle(m_device);
|
||||
|
|
@ -1242,14 +1243,14 @@ bool VulkanWidget::handleDeviceLost()
|
|||
qDebug() << "vkDeviceWaitIdle failed (expected with device lost), continuing recovery...";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Attempt to recreate the device and all resources
|
||||
bool success = recreateDevice();
|
||||
|
||||
|
||||
if (success) {
|
||||
m_deviceLost = false;
|
||||
qDebug() << "Device recovery successful!";
|
||||
|
||||
|
||||
// Restart rendering timer if rendering was enabled
|
||||
if (m_renderingEnabled && m_renderTimer && !m_renderTimer->isActive()) {
|
||||
m_renderTimer->start(16); // ~60 FPS
|
||||
|
|
@ -1258,21 +1259,21 @@ bool VulkanWidget::handleDeviceLost()
|
|||
} else {
|
||||
qDebug() << "Device recovery failed!";
|
||||
}
|
||||
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool VulkanWidget::recreateDevice()
|
||||
{
|
||||
qDebug() << "=== Recreating Vulkan device ===";
|
||||
|
||||
|
||||
// Clean up renderer first
|
||||
if (m_renderer) {
|
||||
delete m_renderer;
|
||||
m_renderer = nullptr;
|
||||
qDebug() << "Renderer cleaned up";
|
||||
}
|
||||
|
||||
|
||||
// Clean up sync objects
|
||||
if (m_device != VK_NULL_HANDLE) {
|
||||
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||||
|
|
@ -1288,16 +1289,16 @@ bool VulkanWidget::recreateDevice()
|
|||
}
|
||||
qDebug() << "Sync objects cleaned up";
|
||||
}
|
||||
|
||||
|
||||
m_renderFinishedSemaphores.clear();
|
||||
m_imageAvailableSemaphores.clear();
|
||||
m_inFlightFences.clear();
|
||||
|
||||
|
||||
// Clean up command objects
|
||||
if (m_device != VK_NULL_HANDLE && m_commandPool != VK_NULL_HANDLE) {
|
||||
if (!m_commandBuffers.empty()) {
|
||||
vkFreeCommandBuffers(m_device, m_commandPool,
|
||||
static_cast<uint32_t>(m_commandBuffers.size()),
|
||||
vkFreeCommandBuffers(m_device, m_commandPool,
|
||||
static_cast<uint32_t>(m_commandBuffers.size()),
|
||||
m_commandBuffers.data());
|
||||
m_commandBuffers.clear();
|
||||
}
|
||||
|
|
@ -1305,10 +1306,10 @@ bool VulkanWidget::recreateDevice()
|
|||
m_commandPool = VK_NULL_HANDLE;
|
||||
qDebug() << "Command objects cleaned up";
|
||||
}
|
||||
|
||||
|
||||
// Clean up swapchain
|
||||
cleanupSwapchain();
|
||||
|
||||
|
||||
// Destroy logical device
|
||||
if (m_device != VK_NULL_HANDLE) {
|
||||
vkDestroyDevice(m_device, nullptr);
|
||||
|
|
@ -1316,14 +1317,14 @@ bool VulkanWidget::recreateDevice()
|
|||
m_queue = VK_NULL_HANDLE;
|
||||
qDebug() << "Logical device destroyed";
|
||||
}
|
||||
|
||||
|
||||
// Destroy surface
|
||||
if (m_surface != VK_NULL_HANDLE) {
|
||||
vkDestroySurfaceKHR(m_instance, m_surface, nullptr);
|
||||
m_surface = VK_NULL_HANDLE;
|
||||
qDebug() << "Surface destroyed";
|
||||
}
|
||||
|
||||
|
||||
// Close and reset X11 display (Linux only) - will be reopened when creating new surface
|
||||
#ifdef __linux__
|
||||
if (m_x11Display) {
|
||||
|
|
@ -1332,21 +1333,21 @@ bool VulkanWidget::recreateDevice()
|
|||
qDebug() << "X11 display closed for recreation";
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Now recreate everything from surface onwards
|
||||
|
||||
|
||||
// Important: Add a small delay to let the GPU driver fully reset
|
||||
// This prevents VK_ERROR_SURFACE_LOST_KHR on some systems
|
||||
qDebug() << "Waiting for GPU driver to stabilize...";
|
||||
QThread::msleep(200); // 200ms delay
|
||||
|
||||
|
||||
// Step 1: Recreate surface
|
||||
if (!createSurface()) {
|
||||
setError("Failed to recreate surface after device lost");
|
||||
return false;
|
||||
}
|
||||
qDebug() << "Surface recreated";
|
||||
|
||||
|
||||
// Verify the physical device still supports this surface
|
||||
VkBool32 surfaceSupported = VK_FALSE;
|
||||
vkGetPhysicalDeviceSurfaceSupportKHR(m_physicalDevice, m_queueFamilyIndex, m_surface, &surfaceSupported);
|
||||
|
|
@ -1356,14 +1357,14 @@ bool VulkanWidget::recreateDevice()
|
|||
return false;
|
||||
}
|
||||
qDebug() << "Surface support verified";
|
||||
|
||||
|
||||
// Step 2: Recreate logical device
|
||||
if (!createDevice()) {
|
||||
setError("Failed to recreate device after device lost");
|
||||
return false;
|
||||
}
|
||||
qDebug() << "Logical device recreated";
|
||||
|
||||
|
||||
// Step 3: Recreate swapchain
|
||||
// Query surface capabilities again to ensure they're current
|
||||
VkSurfaceCapabilitiesKHR surfaceCaps;
|
||||
|
|
@ -1374,31 +1375,31 @@ bool VulkanWidget::recreateDevice()
|
|||
return false;
|
||||
}
|
||||
qDebug() << "Surface capabilities validated";
|
||||
|
||||
|
||||
if (!createSwapchain()) {
|
||||
setError("Failed to recreate swapchain after device lost");
|
||||
return false;
|
||||
}
|
||||
qDebug() << "Swapchain recreated";
|
||||
|
||||
|
||||
// Step 4: Recreate command objects
|
||||
if (!createCommandObjects()) {
|
||||
setError("Failed to recreate command objects after device lost");
|
||||
return false;
|
||||
}
|
||||
qDebug() << "Command objects recreated";
|
||||
|
||||
|
||||
// Step 5: Recreate synchronization objects
|
||||
if (!createSyncObjects()) {
|
||||
setError("Failed to recreate sync objects after device lost");
|
||||
return false;
|
||||
}
|
||||
qDebug() << "Sync objects recreated";
|
||||
|
||||
|
||||
// Step 6: Recreate VulkanRenderer
|
||||
if (m_surfaceWidth >= 100 && m_surfaceHeight >= 100) {
|
||||
m_renderer = new VulkanRenderer();
|
||||
|
||||
|
||||
// Get swapchain format
|
||||
VkSurfaceFormatKHR surfaceFormat;
|
||||
uint32_t formatCount = 0;
|
||||
|
|
@ -1408,7 +1409,7 @@ bool VulkanWidget::recreateDevice()
|
|||
vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, formats.data());
|
||||
surfaceFormat = formats[0];
|
||||
}
|
||||
|
||||
|
||||
// Initialize renderer
|
||||
if (!m_renderer->initialize(m_device, m_physicalDevice,
|
||||
m_queue, m_queueFamilyIndex,
|
||||
|
|
@ -1419,13 +1420,13 @@ bool VulkanWidget::recreateDevice()
|
|||
m_renderer = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
qDebug() << "VulkanRenderer recreated successfully!";
|
||||
}
|
||||
|
||||
|
||||
// Reset frame counter
|
||||
m_currentFrame = 0;
|
||||
|
||||
|
||||
qDebug() << "=== Device recreation complete ===";
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Auto-generated version information from CMakeLists.txt
|
||||
# DO NOT EDIT THIS FILE MANUALLY - Edit CMakeLists.txt instead
|
||||
# This file is sourced by shell scripts to get version information
|
||||
|
||||
APP_VERSION_MAJOR=1
|
||||
APP_VERSION_MINOR=3
|
||||
APP_VERSION_PATCH=0
|
||||
APP_VERSION="1.3.0"
|
||||
|
||||
# Export for use in other scripts
|
||||
export APP_VERSION_MAJOR
|
||||
export APP_VERSION_MINOR
|
||||
export APP_VERSION_PATCH
|
||||
export APP_VERSION
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Auto-generated version information from CMakeLists.txt
|
||||
# DO NOT EDIT THIS FILE MANUALLY - Edit CMakeLists.txt instead
|
||||
# This file is sourced by shell scripts to get version information
|
||||
|
||||
APP_VERSION_MAJOR=@PROJECT_VERSION_MAJOR@
|
||||
APP_VERSION_MINOR=@PROJECT_VERSION_MINOR@
|
||||
APP_VERSION_PATCH=@PROJECT_VERSION_PATCH@
|
||||
APP_VERSION="@PROJECT_VERSION@"
|
||||
|
||||
# Export for use in other scripts
|
||||
export APP_VERSION_MAJOR
|
||||
export APP_VERSION_MINOR
|
||||
export APP_VERSION_PATCH
|
||||
export APP_VERSION
|
||||
Loading…
Reference in New Issue