cmake_minimum_required(VERSION 3.20) project(ClientAll LANGUAGES C CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) if(MSVC) # Source files should be saved as UTF-8 with BOM; compile source and # execution charsets as UTF-8 instead of setting encodings in code. add_compile_options(/utf-8) endif() # Qt global config. Qt is intentionally not hard-coded here; configure it with # CMake-recognized environment variables such as CMAKE_PREFIX_PATH or Qt5_DIR. set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) find_package(Qt5 REQUIRED COMPONENTS Core Network Gui Widgets) get_target_property(QT_QMAKE_EXECUTABLE Qt5::qmake IMPORTED_LOCATION) get_filename_component(QT_BIN_DIR "${QT_QMAKE_EXECUTABLE}" DIRECTORY) find_program(QT_LRELEASE_EXECUTABLE NAMES lrelease lrelease.exe HINTS "${QT_BIN_DIR}" REQUIRED) find_program(QT_LUPDATE_EXECUTABLE NAMES lupdate lupdate.exe HINTS "${QT_BIN_DIR}" REQUIRED) set(TRANSLATION_TS "${CMAKE_SOURCE_DIR}/i18n/update-client_zh_CN.ts") set(TRANSLATION_QM "${CMAKE_SOURCE_DIR}/i18n/update-client_zh_CN.qm") set(TRANSLATION_SCAN_DIRS "${CMAKE_SOURCE_DIR}/Common" "${CMAKE_SOURCE_DIR}/Bootstrap" "${CMAKE_SOURCE_DIR}/Launcher" "${CMAKE_SOURCE_DIR}/Updater" "${CMAKE_SOURCE_DIR}/MainApp" ) add_custom_command( OUTPUT "${TRANSLATION_QM}" COMMAND "${QT_LRELEASE_EXECUTABLE}" "${TRANSLATION_TS}" -qm "${TRANSLATION_QM}" DEPENDS "${TRANSLATION_TS}" COMMENT "Compile Qt translation: update-client_zh_CN.qm" VERBATIM ) add_custom_target(update_client_translations ALL DEPENDS "${TRANSLATION_QM}" ) add_custom_target(update_client_lupdate COMMAND "${QT_LUPDATE_EXECUTABLE}" ${TRANSLATION_SCAN_DIRS} -extensions cpp,h -no-obsolete -ts "${TRANSLATION_TS}" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" COMMENT "Update Qt translation source: update-client_zh_CN.ts" VERBATIM ) # Local-only third-party dependencies. The thirdparty directory is ignored by Git. # Windows can use thirdparty/OpenSSL-Win64. Linux normally uses system OpenSSL. set(THIRDPARTY_DIR "${CMAKE_SOURCE_DIR}/thirdparty" CACHE PATH "Local third-party dependency root") if(WIN32) set(SIMCAE_OPENSSL_ROOT "${THIRDPARTY_DIR}/OpenSSL-Win64" CACHE PATH "OpenSSL Win64 root") if(NOT EXISTS "${SIMCAE_OPENSSL_ROOT}/include/openssl") message(FATAL_ERROR "OpenSSL not found: ${SIMCAE_OPENSSL_ROOT}\n" "Copy OpenSSL-Win64 to thirdparty/OpenSSL-Win64, or configure with " "-DSIMCAE_OPENSSL_ROOT=." ) endif() set(OPENSSL_INC "${SIMCAE_OPENSSL_ROOT}/include") set(OPENSSL_LIB_DEBUG "${SIMCAE_OPENSSL_ROOT}/lib/VC/x64/MDd") set(OPENSSL_LIB_RELEASE "${SIMCAE_OPENSSL_ROOT}/lib/VC/x64/MD") foreach(OPENSSL_LIB_DIR IN ITEMS "${OPENSSL_LIB_DEBUG}" "${OPENSSL_LIB_RELEASE}") if(NOT EXISTS "${OPENSSL_LIB_DIR}") message(FATAL_ERROR "OpenSSL library directory not found: ${OPENSSL_LIB_DIR}") endif() endforeach() set(SIMCAE_OPENSSL_LINK_LIBRARIES $<$:${OPENSSL_LIB_DEBUG}/libssl.lib> $<$:${OPENSSL_LIB_DEBUG}/libcrypto.lib> $<$>:${OPENSSL_LIB_RELEASE}/libssl.lib> $<$>:${OPENSSL_LIB_RELEASE}/libcrypto.lib> ) else() find_package(OpenSSL REQUIRED) set(OPENSSL_INC "${OPENSSL_INCLUDE_DIR}") set(SIMCAE_OPENSSL_LINK_LIBRARIES OpenSSL::SSL OpenSSL::Crypto) endif() add_compile_definitions(HAVE_OPENSSL=1) # 统一输出目录。Windows 保持历史 out/bin;Linux 单独输出,避免和 Windows DLL/PDB 混在一起。 if(UNIX AND NOT APPLE) set(SIMCAE_OUTPUT_ROOT ${CMAKE_SOURCE_DIR}/out/linux) else() set(SIMCAE_OUTPUT_ROOT ${CMAKE_SOURCE_DIR}/out) endif() set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${SIMCAE_OUTPUT_ROOT}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${SIMCAE_OUTPUT_ROOT}/bin) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${SIMCAE_OUTPUT_ROOT}/bin) # Bootstrap 使用 Qt 实现跨平台更新交接,避免直接依赖 Win32 API。 add_subdirectory(Bootstrap) # 先编译公共库 add_subdirectory(Common) # 再编译三个业务程序 add_subdirectory(Launcher) add_subdirectory(Updater) add_subdirectory(MainApp) # 默认启动项目 set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT Launcher) # Copy config templates and static resources to output bin folder. if(UNIX AND NOT APPLE AND EXISTS "${CMAKE_SOURCE_DIR}/config/app_config.linux.example.json") set(APP_CONFIG_SOURCE_FILE "${CMAKE_SOURCE_DIR}/config/app_config.linux.example.json") else() set(APP_CONFIG_SOURCE_FILE "${CMAKE_SOURCE_DIR}/config/app_config.example.json") endif() set(CONFIG_SOURCE_DIR "${CMAKE_SOURCE_DIR}/config") set(MANIFEST_PUBLIC_KEY_FILE "${CONFIG_SOURCE_DIR}/manifest_public_key.pem") set(INI_TARGET_FOLDER "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") # app_config.json 包含运行时版本状态;如果存在旧 client.ini,则交给客户端首次启动迁移 file(MAKE_DIRECTORY "${INI_TARGET_FOLDER}") file(MAKE_DIRECTORY "${INI_TARGET_FOLDER}/config") if(NOT EXISTS "${INI_TARGET_FOLDER}/config/app_config.json" AND NOT EXISTS "${INI_TARGET_FOLDER}/client.ini") configure_file("${APP_CONFIG_SOURCE_FILE}" "${INI_TARGET_FOLDER}/config/app_config.json" COPYONLY) endif() foreach(RUNTIME_RESOURCE local_state.json version_policy.dat) if(EXISTS "${CONFIG_SOURCE_DIR}/${RUNTIME_RESOURCE}" AND NOT EXISTS "${INI_TARGET_FOLDER}/config/${RUNTIME_RESOURCE}") configure_file("${CONFIG_SOURCE_DIR}/${RUNTIME_RESOURCE}" "${INI_TARGET_FOLDER}/config/${RUNTIME_RESOURCE}" COPYONLY) endif() endforeach() # 编译阶段同步静态配置资源 add_custom_target(copy_client_resources ALL COMMAND ${CMAKE_COMMAND} -E make_directory ${INI_TARGET_FOLDER} COMMAND ${CMAKE_COMMAND} -E make_directory ${INI_TARGET_FOLDER}/config COMMAND ${CMAKE_COMMAND} -E copy_if_different ${MANIFEST_PUBLIC_KEY_FILE} ${INI_TARGET_FOLDER}/config/manifest_public_key.pem COMMAND ${CMAKE_COMMAND} -E copy_if_different ${MANIFEST_PUBLIC_KEY_FILE} ${INI_TARGET_FOLDER}/manifest_public_key.pem COMMENT "Copy client config directory and manifest public key to output bin folder" ) add_dependencies(Launcher copy_client_resources) add_dependencies(Updater copy_client_resources) add_dependencies(MainApp copy_client_resources) add_dependencies(Launcher update_client_translations) add_dependencies(Updater update_client_translations) add_dependencies(MainApp update_client_translations) add_dependencies(Bootstrap update_client_translations) # Install rules for packaging if(EXISTS "${APP_CONFIG_SOURCE_FILE}") install(FILES "${APP_CONFIG_SOURCE_FILE}" DESTINATION bin/config RENAME app_config.json) endif() if(EXISTS "${MANIFEST_PUBLIC_KEY_FILE}") install(FILES "${MANIFEST_PUBLIC_KEY_FILE}" DESTINATION bin/config) install(FILES "${MANIFEST_PUBLIC_KEY_FILE}" DESTINATION bin) endif()