376 lines
16 KiB
CMake
376 lines
16 KiB
CMake
cmake_minimum_required(VERSION 3.16)
|
||
project(fpv_relay_cpp LANGUAGES C CXX)
|
||
|
||
# devourer(用户态 USB 驱动) 需要 C++20;本项目其余代码向后兼容,统一用 C++20。
|
||
set(CMAKE_CXX_STANDARD 20)
|
||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||
set(CMAKE_C_STANDARD 11)
|
||
|
||
if(NOT CMAKE_BUILD_TYPE)
|
||
set(CMAKE_BUILD_TYPE Release CACHE STRING "" FORCE)
|
||
endif()
|
||
|
||
# ---------------- 选项 ----------------
|
||
option(FPC_BUILD_WFB_CAPTURE "编译 wfb-ng pcap 采集模块(仅 Linux)" ON)
|
||
if(WIN32)
|
||
set(_fpc_usb_default ON)
|
||
else()
|
||
set(_fpc_usb_default OFF)
|
||
endif()
|
||
option(FPC_BUILD_WFB_USB "编译 devourer(USB) 无线采集/上行" ${_fpc_usb_default})
|
||
option(FPC_BUILD_GUI "编译 Qt 图形界面" OFF)
|
||
|
||
# Qt 安装前缀:由 CMakePresets.json 的 FPC_QT_PREFIX 指定(也可用 -D 覆盖)。
|
||
set(FPC_QT_PREFIX "" CACHE PATH "Qt 安装前缀")
|
||
set(FPC_DEVOURER_GIT_TAG "30d248e021f35be0a8fe85c84939a57a45756901" CACHE STRING "devourer 固定 commit")
|
||
# 本地 devourer 源码目录(可选):设了就用本地,否则联网 FetchContent 拉取。
|
||
# 也支持把源码放到 3rd/devourer(存在即自动使用,免联网)。
|
||
set(FPC_DEVOURER_SRC "" CACHE PATH "本地 devourer 源码目录(可选)")
|
||
|
||
# 编译产物输出目录:所有可执行文件/运行库/示例配置都汇总到这里
|
||
set(FPC_DIST_DIR "${CMAKE_BINARY_DIR}/dist" CACHE PATH "编译产物输出目录")
|
||
# Windows 运行期依赖(libusb/libsodium 的 bin/include/lib)与 ffmpeg.exe(预览解码)。
|
||
# 默认使用仓库内 vendored 的 3rd/win-deps 与 3rd/ffmpeg;也可用环境变量
|
||
# FPV_DEPS_PREFIX / FFMPEG_EXE 或 -D 覆盖。
|
||
set(FPC_DEPS_PREFIX "$ENV{FPV_DEPS_PREFIX}" CACHE PATH "libusb/libsodium 前缀(Windows)")
|
||
if(NOT FPC_DEPS_PREFIX AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/3rd/win-deps/include/libusb-1.0/libusb.h")
|
||
set(FPC_DEPS_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/3rd/win-deps" CACHE PATH "libusb/libsodium 前缀(Windows)" FORCE)
|
||
endif()
|
||
set(FPC_FFMPEG_EXE "$ENV{FFMPEG_EXE}" CACHE FILEPATH "ffmpeg.exe 路径(视频预览解码)")
|
||
if(NOT FPC_FFMPEG_EXE AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/3rd/ffmpeg/ffmpeg.exe")
|
||
set(FPC_FFMPEG_EXE "${CMAKE_CURRENT_SOURCE_DIR}/3rd/ffmpeg/ffmpeg.exe" CACHE FILEPATH "ffmpeg.exe 路径(视频预览解码)" FORCE)
|
||
endif()
|
||
|
||
# ---------------- 第三方库 ----------------
|
||
set(YAML_CPP_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
||
set(YAML_CPP_BUILD_TOOLS OFF CACHE BOOL "" FORCE)
|
||
set(YAML_CPP_BUILD_CONTRIB OFF CACHE BOOL "" FORCE)
|
||
set(YAML_CPP_INSTALL OFF CACHE BOOL "" FORCE)
|
||
add_subdirectory(3rd/yaml-cpp EXCLUDE_FROM_ALL)
|
||
|
||
set(SPDLOG_BUILD_EXAMPLE OFF CACHE BOOL "" FORCE)
|
||
set(SPDLOG_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
||
set(SPDLOG_BUILD_BENCH OFF CACHE BOOL "" FORCE)
|
||
add_subdirectory(3rd/spdlog EXCLUDE_FROM_ALL)
|
||
|
||
add_library(cli11 INTERFACE)
|
||
target_include_directories(cli11 INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/3rd/CLI11/include)
|
||
|
||
# ---------------- devourer(用户态 USB 无线驱动,仅 Jaguar1=RTL8812AU) ----------------
|
||
set(FPC_HAVE_WFB_USB OFF)
|
||
if(FPC_BUILD_WFB_USB)
|
||
# 定位 libusb / libsodium。
|
||
# Windows 上不依赖 pkg-config:直接从 FPC_DEPS_PREFIX 手动查找,
|
||
# 并提供一个 PkgConfig::libusb 导入目标供 devourer 的 CMake 复用。
|
||
if(WIN32 AND FPC_DEPS_PREFIX)
|
||
find_path(FPC_LIBUSB_INCLUDE_DIR libusb-1.0/libusb.h
|
||
HINTS "${FPC_DEPS_PREFIX}/include")
|
||
find_library(FPC_LIBUSB_LIBRARY NAMES usb-1.0 libusb-1.0
|
||
HINTS "${FPC_DEPS_PREFIX}/lib")
|
||
find_path(FPC_SODIUM_INCLUDE_DIR sodium.h HINTS "${FPC_DEPS_PREFIX}/include")
|
||
find_library(FPC_SODIUM_LIBRARY NAMES sodium libsodium HINTS "${FPC_DEPS_PREFIX}/lib")
|
||
if(NOT FPC_LIBUSB_LIBRARY OR NOT FPC_SODIUM_LIBRARY)
|
||
message(FATAL_ERROR
|
||
"未在 FPC_DEPS_PREFIX=${FPC_DEPS_PREFIX} 找到 libusb/libsodium。"
|
||
"请设置环境变量 FPV_DEPS_PREFIX 指向含 include/lib/bin 的前缀目录。")
|
||
endif()
|
||
add_library(PkgConfig::libusb INTERFACE IMPORTED)
|
||
target_include_directories(PkgConfig::libusb INTERFACE "${FPC_LIBUSB_INCLUDE_DIR}")
|
||
target_link_libraries(PkgConfig::libusb INTERFACE "${FPC_LIBUSB_LIBRARY}")
|
||
set(SODIUM_INCLUDE_DIRS "${FPC_SODIUM_INCLUDE_DIR}")
|
||
set(SODIUM_LIBRARIES "${FPC_SODIUM_LIBRARY}")
|
||
set(SODIUM_LIBRARY_DIRS "")
|
||
else()
|
||
find_package(PkgConfig REQUIRED)
|
||
pkg_check_modules(LIBUSB REQUIRED IMPORTED_TARGET libusb-1.0)
|
||
pkg_check_modules(SODIUM REQUIRED libsodium)
|
||
endif()
|
||
|
||
# 只编 RTL8812AU/8811AU/8821AU(Jaguar1),其余后端关闭以缩小体积与依赖。
|
||
set(DEVOURER_JAGUAR1 ON CACHE BOOL "" FORCE)
|
||
set(DEVOURER_8814 OFF CACHE BOOL "" FORCE)
|
||
set(DEVOURER_JAGUAR2_8822B OFF CACHE BOOL "" FORCE)
|
||
set(DEVOURER_JAGUAR2_8821C OFF CACHE BOOL "" FORCE)
|
||
set(DEVOURER_JAGUAR3_8822C OFF CACHE BOOL "" FORCE)
|
||
set(DEVOURER_JAGUAR3_8822E OFF CACHE BOOL "" FORCE)
|
||
set(DEVOURER_8733B OFF CACHE BOOL "" FORCE)
|
||
set(DEVOURER_KESTREL_8852B OFF CACHE BOOL "" FORCE)
|
||
set(DEVOURER_KESTREL_8852C OFF CACHE BOOL "" FORCE)
|
||
set(DEVOURER_MT7612U OFF CACHE BOOL "" FORCE)
|
||
set(DEVOURER_PCIE OFF CACHE BOOL "" FORCE)
|
||
|
||
include(FetchContent)
|
||
# CMake 4.x:允许 FetchContent_Populate(不把 devourer 的示例/测试加进默认构建)
|
||
if(POLICY CMP0169)
|
||
cmake_policy(SET CMP0169 OLD)
|
||
endif()
|
||
|
||
# 1) 本地源码优先:FPC_DEVOURER_SRC,或仓库内 3rd/devourer
|
||
if(NOT FPC_DEVOURER_SRC AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/3rd/devourer/CMakeLists.txt")
|
||
set(FPC_DEVOURER_SRC "${CMAKE_CURRENT_SOURCE_DIR}/3rd/devourer")
|
||
endif()
|
||
# 2) 清掉失效的 FETCHCONTENT_SOURCE_DIR_DEVOURER(指向已删除的目录会让 configure 报错)
|
||
if(DEFINED FETCHCONTENT_SOURCE_DIR_DEVOURER AND NOT EXISTS "${FETCHCONTENT_SOURCE_DIR_DEVOURER}")
|
||
unset(FETCHCONTENT_SOURCE_DIR_DEVOURER CACHE)
|
||
endif()
|
||
|
||
if(FPC_DEVOURER_SRC AND EXISTS "${FPC_DEVOURER_SRC}/CMakeLists.txt")
|
||
message(STATUS "使用本地 devourer: ${FPC_DEVOURER_SRC}")
|
||
add_subdirectory("${FPC_DEVOURER_SRC}" "${CMAKE_BINARY_DIR}/devourer-build" EXCLUDE_FROM_ALL)
|
||
else()
|
||
FetchContent_Declare(devourer
|
||
GIT_REPOSITORY https://github.com/openipc/devourer.git
|
||
GIT_TAG ${FPC_DEVOURER_GIT_TAG}
|
||
GIT_SHALLOW TRUE)
|
||
FetchContent_GetProperties(devourer)
|
||
if(NOT devourer_POPULATED)
|
||
FetchContent_Populate(devourer)
|
||
endif()
|
||
add_subdirectory(${devourer_SOURCE_DIR} ${devourer_BINARY_DIR} EXCLUDE_FROM_ALL)
|
||
endif()
|
||
set(FPC_HAVE_WFB_USB ON)
|
||
endif()
|
||
|
||
# ---------------- wfb-ng 静态库(FEC/解密/加密) ----------------
|
||
# Linux pcap 采集版:含 tx.cpp(AF_PACKET 注入)。
|
||
if(FPC_BUILD_WFB_CAPTURE AND UNIX AND NOT APPLE)
|
||
find_package(PkgConfig REQUIRED)
|
||
pkg_check_modules(SODIUM REQUIRED libsodium)
|
||
pkg_check_modules(PCAP REQUIRED libpcap)
|
||
|
||
add_library(wfbng STATIC
|
||
3rd/wfb-ng/src/rx.cpp
|
||
3rd/wfb-ng/src/tx.cpp
|
||
3rd/wfb-ng/src/wifibroadcast.cpp
|
||
3rd/wfb-ng/src/radiotap.c
|
||
3rd/wfb-ng/src/zfex.c
|
||
)
|
||
target_compile_definitions(wfbng PRIVATE __WFB_RX_SHARED_LIBRARY__ FPC_WFB_TX_NO_MAIN)
|
||
target_include_directories(wfbng PUBLIC
|
||
3rd/wfb-ng/src
|
||
${SODIUM_INCLUDE_DIRS}
|
||
${PCAP_INCLUDE_DIRS}
|
||
)
|
||
target_link_libraries(wfbng PUBLIC ${SODIUM_LIBRARIES} ${PCAP_LIBRARIES})
|
||
# wfb-ng 对报文做了大量指针类型转换,必须关闭严格别名优化,否则解密会失败
|
||
target_compile_options(wfbng PRIVATE -w -fno-strict-aliasing)
|
||
set(FPC_HAVE_WFB_CAPTURE ON)
|
||
endif()
|
||
|
||
# Windows(或仅 USB)版:只编 Aggregator,不含 pcap Receiver / AF_PACKET tx。
|
||
if(FPC_HAVE_WFB_USB AND NOT TARGET wfbng)
|
||
add_library(wfbng STATIC
|
||
3rd/wfb-ng/src/rx.cpp
|
||
3rd/wfb-ng/src/wifibroadcast.cpp
|
||
3rd/wfb-ng/src/radiotap.c
|
||
3rd/wfb-ng/src/zfex.c
|
||
)
|
||
target_compile_definitions(wfbng PRIVATE __WFB_RX_SHARED_LIBRARY__)
|
||
target_include_directories(wfbng PUBLIC 3rd/wfb-ng/src ${SODIUM_INCLUDE_DIRS})
|
||
target_link_directories(wfbng PUBLIC ${SODIUM_LIBRARY_DIRS})
|
||
target_link_libraries(wfbng PUBLIC ${SODIUM_LIBRARIES})
|
||
if(NOT MSVC)
|
||
target_compile_options(wfbng PRIVATE -w -fno-strict-aliasing)
|
||
endif()
|
||
endif()
|
||
|
||
# ---------------- 核心库(采集/转发/录制/RTSP/状态) ----------------
|
||
set(FPC_CORE_SRC
|
||
${CMAKE_CURRENT_SOURCE_DIR}/src/capture/capture.cpp
|
||
${CMAKE_CURRENT_SOURCE_DIR}/src/capture/radio.cpp
|
||
${CMAKE_CURRENT_SOURCE_DIR}/src/capture/udp_capture.cpp
|
||
${CMAKE_CURRENT_SOURCE_DIR}/src/capture/wfb_uplink.cpp
|
||
${CMAKE_CURRENT_SOURCE_DIR}/src/config/config.cpp
|
||
${CMAKE_CURRENT_SOURCE_DIR}/src/relay/dvr_sink.cpp
|
||
${CMAKE_CURRENT_SOURCE_DIR}/src/relay/h265.cpp
|
||
${CMAKE_CURRENT_SOURCE_DIR}/src/relay/stream.cpp
|
||
${CMAKE_CURRENT_SOURCE_DIR}/src/relay/udp_sink.cpp
|
||
${CMAKE_CURRENT_SOURCE_DIR}/src/rtsp/rtsp_server.cpp
|
||
${CMAKE_CURRENT_SOURCE_DIR}/src/status/http_server.cpp
|
||
)
|
||
|
||
# Linux pcap 采集(wfb_capture.cpp 依赖 pcap/radiotap)。
|
||
if(FPC_HAVE_WFB_CAPTURE AND NOT WIN32)
|
||
list(APPEND FPC_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/capture/wfb_capture.cpp)
|
||
endif()
|
||
|
||
# USB(devourer) 采集 + 上行。
|
||
if(FPC_HAVE_WFB_USB)
|
||
list(APPEND FPC_CORE_SRC
|
||
${CMAKE_CURRENT_SOURCE_DIR}/src/capture/wfb_usb_device.cpp
|
||
${CMAKE_CURRENT_SOURCE_DIR}/src/capture/wfb_usb_capture.cpp
|
||
${CMAKE_CURRENT_SOURCE_DIR}/src/capture/wfb_usb_tx.cpp
|
||
)
|
||
endif()
|
||
|
||
add_library(fpv_core STATIC ${FPC_CORE_SRC})
|
||
target_include_directories(fpv_core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||
|
||
if(TARGET yaml-cpp::yaml-cpp)
|
||
set(FPC_YAML_TARGET yaml-cpp::yaml-cpp)
|
||
else()
|
||
set(FPC_YAML_TARGET yaml-cpp)
|
||
endif()
|
||
|
||
find_package(Threads REQUIRED)
|
||
target_link_libraries(fpv_core PUBLIC ${FPC_YAML_TARGET} spdlog::spdlog Threads::Threads)
|
||
|
||
if(FPC_HAVE_WFB_CAPTURE)
|
||
target_compile_definitions(fpv_core PUBLIC FPC_HAVE_WFB_CAPTURE=1)
|
||
target_link_libraries(fpv_core PUBLIC wfbng)
|
||
endif()
|
||
|
||
if(FPC_HAVE_WFB_USB)
|
||
target_compile_definitions(fpv_core PUBLIC FPC_HAVE_WFB_USB=1)
|
||
target_link_libraries(fpv_core PUBLIC wfbng devourer)
|
||
endif()
|
||
|
||
# Windows 平台:统一编译宏 + 链接 Winsock。
|
||
if(WIN32)
|
||
target_compile_definitions(fpv_core PUBLIC
|
||
WIN32_LEAN_AND_MEAN
|
||
NOMINMAX
|
||
_WIN32_WINNT=0x0601
|
||
_CRT_SECURE_NO_WARNINGS
|
||
)
|
||
target_link_libraries(fpv_core PUBLIC ws2_32)
|
||
# 强制 winsock2.h 先于 windows.h(spdlog/Qt/devourer 会间接包含 windows.h)。
|
||
if(MSVC)
|
||
target_compile_options(fpv_core PUBLIC /FIwinsock2.h)
|
||
else()
|
||
target_compile_options(fpv_core PUBLIC -include winsock2.h)
|
||
endif()
|
||
endif()
|
||
|
||
# ============================================================================
|
||
# 编译产物汇总到 FPC_DIST_DIR:可执行文件 + 运行期依赖 + 示例配置 + 密钥
|
||
# ============================================================================
|
||
set(FPC_STAGE_CMDS
|
||
COMMAND ${CMAKE_COMMAND} -E make_directory "${FPC_DIST_DIR}"
|
||
)
|
||
# 示例配置与密钥
|
||
foreach(_f config.example.yaml config.windows.example.yaml)
|
||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${_f}")
|
||
list(APPEND FPC_STAGE_CMDS
|
||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||
"${CMAKE_CURRENT_SOURCE_DIR}/${_f}" "${FPC_DIST_DIR}/")
|
||
endif()
|
||
endforeach()
|
||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/ass/gs.key")
|
||
list(APPEND FPC_STAGE_CMDS
|
||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||
"${CMAKE_CURRENT_SOURCE_DIR}/ass/gs.key" "${FPC_DIST_DIR}/gs.key")
|
||
endif()
|
||
# 本地 config.yaml(若存在,未被 git 跟踪)也一并带到 dist,方便直接用
|
||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/config.yaml")
|
||
list(APPEND FPC_STAGE_CMDS
|
||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||
"${CMAKE_CURRENT_SOURCE_DIR}/config.yaml" "${FPC_DIST_DIR}/config.yaml")
|
||
endif()
|
||
|
||
# Windows 运行期依赖 DLL(libusb/libsodium/ffmpeg)
|
||
if(WIN32)
|
||
set(_fpc_dep_dlls)
|
||
if(FPC_DEPS_PREFIX)
|
||
file(GLOB _fpc_dep_dlls
|
||
"${FPC_DEPS_PREFIX}/bin/libusb*.dll"
|
||
"${FPC_DEPS_PREFIX}/bin/libsodium*.dll")
|
||
endif()
|
||
if(FPC_FFMPEG_EXE AND EXISTS "${FPC_FFMPEG_EXE}")
|
||
list(APPEND _fpc_dep_dlls "${FPC_FFMPEG_EXE}")
|
||
endif()
|
||
if(_fpc_dep_dlls)
|
||
list(APPEND FPC_STAGE_CMDS
|
||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${_fpc_dep_dlls} "${FPC_DIST_DIR}/")
|
||
endif()
|
||
endif()
|
||
|
||
# ---------------- 命令行程序 ----------------
|
||
add_executable(fpv-relay src/main.cpp)
|
||
target_link_libraries(fpv-relay PRIVATE fpv_core cli11)
|
||
# 可执行文件直接输出到 dist,和运行期依赖放在一起(IDE 直接运行也能找到 DLL)
|
||
set_target_properties(fpv-relay PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${FPC_DIST_DIR}")
|
||
add_custom_command(TARGET fpv-relay POST_BUILD ${FPC_STAGE_CMDS})
|
||
|
||
# ---------------- Qt 图形界面(可选) ----------------
|
||
if(FPC_BUILD_GUI)
|
||
list(APPEND CMAKE_PREFIX_PATH ${FPC_QT_PREFIX})
|
||
find_package(Qt6 REQUIRED COMPONENTS Quick QuickControls2 Svg Widgets Network PrintSupport)
|
||
qt_standard_project_setup()
|
||
|
||
set(FLUENTUI_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
||
set(FLUENTUI_BUILD_STATIC_LIB ON CACHE BOOL "" FORCE)
|
||
add_subdirectory(3rd/FluentUI EXCLUDE_FROM_ALL)
|
||
|
||
# 视频预览不再依赖 GStreamer:运行时调用随程序分发的 ffmpeg.exe 解码
|
||
# (ffmpeg 能解 H264/H265,单文件自包含)。见 src/gui/video_item.cpp。
|
||
qt_add_executable(fpv-relay-gui
|
||
src/gui/main_gui.cpp
|
||
src/gui/backend.cpp
|
||
src/gui/video_item.cpp
|
||
)
|
||
# 可执行文件直接输出到 dist,和 Qt/ffmpeg/libusb 等运行库放在一起
|
||
set_target_properties(fpv-relay-gui PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${FPC_DIST_DIR}")
|
||
target_link_libraries(fpv-relay-gui PRIVATE
|
||
fpv_core
|
||
fluentuiplugin
|
||
Qt6::Quick Qt6::QuickControls2 Qt6::Svg Qt6::Widgets Qt6::Network Qt6::PrintSupport
|
||
)
|
||
target_compile_definitions(fpv-relay-gui PRIVATE FLUENTUI_BUILD_STATIC_LIB)
|
||
|
||
qt_add_qml_module(fpv-relay-gui
|
||
URI FpvRelay
|
||
VERSION 1.0
|
||
QML_FILES
|
||
src/gui/qml/App.qml
|
||
src/gui/qml/DroneCard.qml
|
||
src/gui/qml/Settings.qml
|
||
)
|
||
|
||
# GUI 产物汇总(exe 与 FpvRelay QML 模块已随 RUNTIME_OUTPUT_DIRECTORY 落到 dist)
|
||
set(FPC_GUI_STAGE)
|
||
if(WIN32)
|
||
find_program(FPC_WINDEPLOYQT windeployqt HINTS "${FPC_QT_PREFIX}/bin")
|
||
if(FPC_WINDEPLOYQT)
|
||
list(APPEND FPC_GUI_STAGE
|
||
COMMAND "${FPC_WINDEPLOYQT}" --release
|
||
--qmldir "${CMAKE_CURRENT_SOURCE_DIR}/src/gui"
|
||
--dir "${FPC_DIST_DIR}" "${FPC_DIST_DIR}/fpv-relay-gui.exe")
|
||
endif()
|
||
# FluentUI 依赖的 Qt5Compat.GraphicalEffects + Qt6ShaderTools
|
||
if(EXISTS "${FPC_QT_PREFIX}/qml/Qt5Compat")
|
||
list(APPEND FPC_GUI_STAGE
|
||
COMMAND ${CMAKE_COMMAND} -E make_directory "${FPC_DIST_DIR}/qml"
|
||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||
"${FPC_QT_PREFIX}/qml/Qt5Compat" "${FPC_DIST_DIR}/qml/Qt5Compat")
|
||
endif()
|
||
if(EXISTS "${FPC_QT_PREFIX}/bin/Qt6ShaderTools.dll")
|
||
list(APPEND FPC_GUI_STAGE
|
||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||
"${FPC_QT_PREFIX}/bin/Qt6ShaderTools.dll" "${FPC_DIST_DIR}/")
|
||
endif()
|
||
# FpvRelay QML 模块目录(生成在构建目录,拷贝到 dist)
|
||
list(APPEND FPC_GUI_STAGE
|
||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||
"${CMAKE_CURRENT_BINARY_DIR}/FpvRelay" "${FPC_DIST_DIR}/FpvRelay")
|
||
# qt.conf:让 Qt 从程序目录找 QML
|
||
file(WRITE "${CMAKE_BINARY_DIR}/fpc_qt.conf" "[Paths]\nPrefix=.\nQmlImportsPath=qml\n")
|
||
list(APPEND FPC_GUI_STAGE
|
||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||
"${CMAKE_BINARY_DIR}/fpc_qt.conf" "${FPC_DIST_DIR}/qt.conf")
|
||
# windeployqt 拷的是 Qt 自带的 MinGW 运行库;若编译器版本不同,用编译器自带的覆盖。
|
||
if(MINGW)
|
||
get_filename_component(_fpc_mingw_bin "${CMAKE_CXX_COMPILER}" DIRECTORY)
|
||
foreach(_rt libstdc++-6.dll libgcc_s_seh-1.dll libwinpthread-1.dll)
|
||
if(EXISTS "${_fpc_mingw_bin}/${_rt}")
|
||
list(APPEND FPC_GUI_STAGE
|
||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||
"${_fpc_mingw_bin}/${_rt}" "${FPC_DIST_DIR}/")
|
||
endif()
|
||
endforeach()
|
||
endif()
|
||
endif()
|
||
# 依赖 DLL / 配置 / 密钥的汇总也挂到 GUI 目标,避免只构建 GUI 时缺失
|
||
add_custom_command(TARGET fpv-relay-gui POST_BUILD ${FPC_STAGE_CMDS} ${FPC_GUI_STAGE})
|
||
endif()
|