Files
tokisaki galaxy bb4c48505a server: accept a semver prerelease suffix in the product version
The validation added in #1084 rejected anything but digits and dots, which is
narrower than semver: a prerelease suffix after a hyphen is part of the spec,
and the native about page's ParseVersion already strips such a suffix for the
update check while displaying it verbatim. Allow exactly one hyphen segment of
[0-9A-Za-z.-] after the numeric body, so dev builds can embed
0.7.1-dev.20261019.<hash> and the about page shows the full string.
version.txt itself stays bare MAJOR.MINOR.PATCH and every release passes
unchanged.

lcompile-release.ps1 feeds the same override locally, so its ValidatePattern
loosens in step.
2026-10-19 16:00:20 +08:00

671 lines
28 KiB
CMake
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
cmake_minimum_required(VERSION 3.25.0)
if(POLICY CMP0141)
cmake_policy(SET CMP0141 NEW)
endif()
set(PROJECT_NAME "MetasequoiaImeServer")
cmake_policy(SET CMP0167 NEW)
project(${PROJECT_NAME} VERSION 1.0)
# Release binaries need usable symbols for crash diagnosis. Keep the PDB beside each executable so
# the release job can validate and publish it without changing the binary's install layout.
#
# The debug info is embedded in each object (/Z7) rather than written to a compile-time PDB (/Zi).
# The two produce the same final .pdb once the linker's /DEBUG runs over them, but sccache -- the CI
# compiler cache -- can only cache an MSVC compile whose debug info lives in the object. With /Zi it
# treats every translation unit as uncacheable and the cache sits at a 0% hit rate. /Z7 keeps the
# beside-the-executable PDB the release job expects while letting that cache actually work.
if(MSVC)
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "Embedded")
add_compile_options("$<$<CONFIG:Release>:/Z7>")
add_link_options("$<$<CONFIG:Release>:/DEBUG>")
endif()
include(CTest)
# The engine is a first-party component of this repository, vendored in-tree at engine/ next to
# server/, ui/ and windows/. The remaining third-party sources are still submodules under vendor/.
set(MSIME_REPO_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/..")
set(MSIME_ENGINE_DIR "${MSIME_REPO_ROOT}/engine")
set(MSIME_VENDOR_DIR "${MSIME_REPO_ROOT}/vendor")
# 内置皮肤的出厂清单(skins/default/<id>/skin.toml)编进程序:数据目录里那一份缺失或写坏时,
# 外观仍按出厂清单画。清单是唯一的来源,这里只把它们原样嵌成字符串;改了清单会触发重新配置。
set(MSIME_FACTORY_SKIN_IDS fluent wechat wechat_scroll graphite willow_green autumn_osmanthus microsoft canvas)
set(MSIME_GENERATED_DIR "${CMAKE_BINARY_DIR}/generated")
set(MSIME_VERSION_FILE "${MSIME_REPO_ROOT}/version.txt")
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${MSIME_VERSION_FILE}")
set(MSIME_PRODUCT_VERSION_OVERRIDE "" CACHE STRING "Product version to embed in the settings page")
if(MSIME_PRODUCT_VERSION_OVERRIDE)
set(MSIME_PRODUCT_VERSION "${MSIME_PRODUCT_VERSION_OVERRIDE}")
else()
file(STRINGS "${MSIME_VERSION_FILE}" MSIME_PRODUCT_VERSION LIMIT_COUNT 1)
endif()
string(STRIP "${MSIME_PRODUCT_VERSION}" MSIME_PRODUCT_VERSION)
# 版本主体必须是数字段;允许一个可选的连字符后缀(semver 预发布段),dev-build 用它携带
# 日期与 commit(0.7.1-dev.20261019.<hash>),设置窗口关于页原样显示。关于页的 ParseVersion
# 会剥掉后缀做更新检查的数字比较,所以后缀不影响版本判定。
if(NOT MSIME_PRODUCT_VERSION MATCHES "^[0-9]+(\\.[0-9]+)*(-[0-9A-Za-z.-]+)?$")
message(FATAL_ERROR "Invalid product version in ${MSIME_VERSION_FILE}: '${MSIME_PRODUCT_VERSION}'")
endif()
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/src/msime_version.h.in"
"${MSIME_GENERATED_DIR}/msime_version.h"
@ONLY
)
set(_msime_factory_skins "")
foreach(_skin_id IN LISTS MSIME_FACTORY_SKIN_IDS)
set(_skin_manifest "${MSIME_REPO_ROOT}/skins/default/${_skin_id}/skin.toml")
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${_skin_manifest}")
file(READ "${_skin_manifest}" _skin_text)
string(APPEND _msime_factory_skins "{\"${_skin_id}\", R\"msimeskin(${_skin_text})msimeskin\"},\n")
endforeach()
# 只在内容变了时才写,免得每次配置都让皮肤目录的编译单元重编。
set(_msime_factory_skins_file "${MSIME_GENERATED_DIR}/builtin_skin_manifests.inc")
set(_msime_factory_skins_old "")
if(EXISTS "${_msime_factory_skins_file}")
file(READ "${_msime_factory_skins_file}" _msime_factory_skins_old)
endif()
if(NOT _msime_factory_skins_old STREQUAL _msime_factory_skins)
file(WRITE "${_msime_factory_skins_file}" "${_msime_factory_skins}")
endif()
include_directories("${MSIME_GENERATED_DIR}")
# Boost
# An explicit -DBoost_ROOT wins, then BOOST_ROOT from the environment, and only then the scoop
# layout under the current user's profile. The fallback used to name one developer's home directory,
# which meant anyone else without BOOST_ROOT set got a configure failure pointing at a path that
# does not exist on their machine.
if(NOT DEFINED Boost_ROOT)
if(DEFINED ENV{BOOST_ROOT})
set(Boost_ROOT "$ENV{BOOST_ROOT}")
elseif(DEFINED ENV{USERPROFILE} AND EXISTS "$ENV{USERPROFILE}/scoop/apps/boost/current")
set(Boost_ROOT "$ENV{USERPROFILE}/scoop/apps/boost/current")
endif()
endif()
set (Boost_USE_STATIC_LIBS ON)
find_package(Boost REQUIRED COMPONENTS locale json)
include_directories(${Boost_INCLUDE_DIRS})
# fmt, spdlog and sqlite3
find_package(fmt CONFIG REQUIRED)
find_package(spdlog CONFIG REQUIRED)
find_package(unofficial-sqlite3 CONFIG REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)
find_package(CURL CONFIG REQUIRED)
find_package(ZLIB REQUIRED)
# The engine ships its own CMake target. Consume that instead of listing its
# translation units here, so that adding a file to the engine no longer requires
# a matching edit in this file. EXCLUDE_FROM_ALL keeps the engine's own test
# executables out of the default build.
#
# Which is also why BUILD_TESTING has to be off across that add_subdirectory: the engine registers
# its own add_test() entries behind that flag, and EXCLUDE_FROM_ALL then never builds the
# executables they point at, so ctest reports an "Unable to find executable" failure per entry. The
# engine's own suite runs in the separate Engine job of ci.yml (scripts/ci/test-engine.ps1), which
# builds the engine standalone. Restored immediately afterwards so this repository's own tests/
# still register.
set(_metasequoia_saved_build_testing "${BUILD_TESTING}")
set(BUILD_TESTING OFF)
set(METASEQUOIA_IME_BUILD_VOICE ON CACHE BOOL "" FORCE)
set(MSIME_VOICE_CAPTURE ON CACHE BOOL "" FORCE)
add_subdirectory("${MSIME_ENGINE_DIR}" "${CMAKE_BINARY_DIR}/engine" EXCLUDE_FROM_ALL)
set(BUILD_TESTING "${_metasequoia_saved_build_testing}")
unset(_metasequoia_saved_build_testing)
# Build the OpenCC submodule as a static dependency of the server.
add_subdirectory("${MSIME_VENDOR_DIR}/opencc" "${CMAKE_BINARY_DIR}/opencc" EXCLUDE_FROM_ALL)
# OpenCC's Windows dictionary helper copies the library into the tools output
# directory before MSBuild has necessarily created that directory.
add_custom_target(opencc_tools_output_dir
COMMAND ${CMAKE_COMMAND} -E make_directory
"${CMAKE_BINARY_DIR}/opencc/src/tools/$<CONFIG>"
)
add_dependencies(copy_libopencc_to_dir_of_opencc_dict opencc_tools_output_dir)
# cpp-pinyin: settings uses it to annotate pure-Chinese phrase imports.
set(_cpp_pinyin_saved_shared_libs "${BUILD_SHARED_LIBS}")
set(BUILD_SHARED_LIBS OFF)
set(CPP_PINYIN_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(CPP_PINYIN_INSTALL OFF CACHE BOOL "" FORCE)
add_subdirectory("${MSIME_VENDOR_DIR}/cpp-pinyin" "${CMAKE_BINARY_DIR}/cpp-pinyin" EXCLUDE_FROM_ALL)
set(BUILD_SHARED_LIBS "${_cpp_pinyin_saved_shared_libs}")
unset(_cpp_pinyin_saved_shared_libs)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
add_definitions(
/D_UNICODE=1
/DUNICODE=1
/DFANY_DEBUG=1
)
# HandwritingPanel still uses the legacy <experimental/coroutine>; on newer
# MSVC STL the deprecation is a hard error, so silence it explicitly.
add_definitions(/D_SILENCE_EXPERIMENTAL_COROUTINE_DEPRECATION_WARNINGS)
# add_definitions(
# /DFANY_DEBUG=1
# /DFANY_IPC_DEBUG=1
# )
# For utf8cpp, make it use C++11 and later
add_compile_options(/Zc:__cplusplus /FS /utf-8)
include_directories("./")
include_directories("./src/")
# The repository root is on the include path so engine headers are reached as "engine/...", which
# names the component the same way the source tree does.
include_directories("${MSIME_REPO_ROOT}")
include_directories("${MSIME_VENDOR_DIR}")
include_directories("${MSIME_ENGINE_DIR}/utfcpp/source/")
set(MY_EXECUTABLE_NAME "MetasequoiaImeServer")
set(WATCHDOG_EXECUTABLE_NAME "MetasequoiaImeWatchdog")
set(DICTIONARY_REPLAY_EXECUTABLE_NAME "MetasequoiaImeDictionaryReplay")
add_executable(${WATCHDOG_EXECUTABLE_NAME} WIN32
"./src/watchdog/main.cpp"
"./src/watchdog/watchdog_protocol.h"
"./src/utils/single_instance.h"
"./src/resource/resource.h"
"./src/resource/resource.rc"
)
target_compile_definitions(${WATCHDOG_EXECUTABLE_NAME} PRIVATE
NOMINMAX=1
WIN32_LEAN_AND_MEAN=1
)
target_link_libraries(${WATCHDOG_EXECUTABLE_NAME} PRIVATE shell32 ole32)
if(MSVC)
target_compile_options(${WATCHDOG_EXECUTABLE_NAME} PRIVATE /W4 /permissive-)
endif()
set(SRC_FILES
"./src/ai/ai_assistant.cpp"
"./src/ai/ai_assistant.h"
"./src/ai/ai_assistant_cache.cpp"
"./src/ai/ai_assistant_cache.h"
"./src/ai/ai_assistant_cache_key.cpp"
"./src/ai/ai_assistant_cache_key.h"
"./src/ai/ai_assistant_request.cpp"
"./src/ai/ai_assistant_request.h"
"./src/ai/ai_provider_store.cpp"
"./src/ai/ai_provider_store.h"
"./src/config/ai_provider.h"
"./src/ai/chat_completions.cpp"
"./src/ai/jev_client.cpp"
"./src/ai/chat_completions.h"
"./src/ai/chat_request_params.h"
"./src/clipboard/clipboard_history.cpp"
"./src/clipboard/clipboard_history.h"
"./src/cloud/ai_translation.cpp"
"./src/cloud/ai_translation.h"
"./src/cloud/cloud_ime.cpp"
"./src/cloud/cloud_ime.h"
"./src/cloud/cloud_translation.cpp"
"./src/cloud/cloud_translation.h"
"./src/cloud/custom_translation.cpp"
"./src/cloud/custom_translation.h"
"./src/cloud/niutrans_translation.cpp"
"./src/cloud/niutrans_translation.h"
"./src/cloud/tencent_tmt.cpp"
"./src/cloud/tencent_tmt.h"
"./src/cloud/translation_gloss.cpp"
"./src/cloud/translation_gloss.h"
"./src/config/credential_protection.cpp"
"./src/config/credential_protection.h"
"./src/config/ime_config.cpp"
"./src/config/ime_config_credentials.cpp"
"./src/config/ime_config.h"
"./src/config/ime_config_appearance.cpp"
"./src/config/ime_config_fonts.cpp"
"./src/config/ime_config_general.cpp"
"./src/config/ime_config_input.cpp"
"./src/config/ime_config_internal.h"
"./src/config/ime_config_keys.cpp"
"./src/config/ime_config_services.cpp"
"./src/config/ime_config_shuangpin.cpp"
"./src/config/ime_config_template.cpp"
"./src/config/ime_config_theme.cpp"
"./src/config/ime_config_toml.cpp"
"./src/config/ime_config_toolbar.cpp"
"./src/config/ime_config_write.cpp"
"./src/conversion/chinese_converter.cpp"
"./src/conversion/chinese_converter.h"
"./src/defines/defines.h"
"./src/english/english_ime.cpp"
"./src/english/english_ime.h"
"./src/global/globals.h"
"./src/ipc/candidate_translation_policy.h"
"./src/ipc/event_listener.cpp"
"./src/ipc/event_listener.h"
"./src/ipc/event_listener_async_candidates.cpp"
"./src/ipc/event_listener_candidates.cpp"
"./src/ipc/event_listener_internal.h"
"./src/ipc/event_listener_keys.cpp"
"./src/ipc/event_listener_pipes.cpp"
"./src/ipc/event_listener_selection.cpp"
"./src/ipc/event_listener_worker.cpp"
"./src/ipc/ipc.cpp"
"./src/ipc/ipc.h"
"./src/ipc/voice_composition_pipe.h"
"./src/ipc/voice_control_dispatch.cpp"
"./src/ipc/voice_control_dispatch.h"
"./src/mixed/date_time_candidates.h"
"./src/mixed/mixed_candidates.cpp"
"./src/mixed/mixed_candidates.h"
"./src/log/fanylog.cpp"
"./src/log/fanylog.h"
"./src/log/candidate_diag_log.cpp"
"./src/log/candidate_diag_log.h"
"./src/log/ftb_diag_log.h"
"./src/resource/resource.h"
"./src/resource/resource.rc"
"./src/settings/settings_launcher.cpp"
"./src/settings/settings_launcher.h"
"./src/settings/api_credential_test.cpp"
"./src/settings/api_credential_test.h"
"./src/settings/api_credential_test_request.h"
"./src/settings/collocation_model.cpp"
"./src/settings/collocation_model.h"
"./src/skin/candidate_skin_catalog.cpp"
"./src/skin/candidate_skin_catalog.h"
"./src/session/engine_input_session.cpp"
"./src/session/engine_input_session.h"
"./src/session/input_session.h"
"./src/session/session_factory.cpp"
"./src/session/session_factory.h"
"./src/statistics/stats_aggregate.cpp"
"./src/statistics/stats_aggregate.h"
"./src/statistics/stats_candidate_capture.cpp"
"./src/statistics/stats_candidate_capture.h"
"./src/statistics/stats_frames.cpp"
"./src/statistics/stats_frames.h"
"./src/statistics/stats_pipe.cpp"
"./src/statistics/stats_pipe.h"
"./src/statistics/stats_store.cpp"
"./src/statistics/stats_store.h"
"./src/statistics/stats_types.h"
"./src/utils/candidate_size_estimator.cpp"
"./src/utils/candidate_size_estimator.h"
"./src/utils/common_utils.cpp"
"./src/utils/common_utils.h"
"./src/utils/hanzi_pinyin.cpp"
"./src/utils/hanzi_pinyin.h"
"./src/utils/ime_paths.cpp"
"./src/utils/ime_utils.cpp"
"./src/utils/ime_utils.h"
"./src/utils/network_proxy.cpp"
"./src/utils/network_proxy.h"
"./src/utils/serial_task_runner.cpp"
"./src/utils/serial_task_runner.h"
"./src/utils/shuangpin_preedit_display.cpp"
"./src/utils/shuangpin_preedit_display.h"
"./src/utils/window_utils.cpp"
"./src/utils/window_utils.h"
"./src/window/candidate_presenter.cpp"
"./src/window/candidate_presenter.h"
"./src/window/candidate_skin_layers.cpp"
"./src/window/candidate_skin_layers.h"
"./src/window/candidate_skin_overlay.cpp"
"./src/window/candidate_skin_overlay.h"
"./src/window/candidate_skin_palette.cpp"
"./src/window/candidate_skin_palette.h"
"./src/window/candidate_skin_scene.cpp"
"./src/window/candidate_skin_scene.h"
"./src/window/candidate_skin_tokens.cpp"
"./src/window/candidate_skin_tokens.h"
"./src/window/tray_menu_presenter.cpp"
"./src/window/tray_menu_presenter.h"
"./src/window/floating_toolbar_presenter.cpp"
"./src/window/floating_toolbar_presenter.h"
"./src/window/floating_toolbar_skin.cpp"
"./src/window/floating_toolbar_skin.h"
"./src/window/caret_state_indicator.cpp"
"./src/window/caret_state_indicator.h"
"./src/window/ime_windows.cpp"
"./src/window/ime_windows.h"
"./src/window/ime_windows_candidate.cpp"
"./src/window/ime_windows_internal.h"
"./src/window/ime_windows_menu.cpp"
"./src/window/ime_windows_toolbar.cpp"
"./src/window/small_windows.cpp"
"./src/window/small_windows.h"
"./src/window/window_hook.cpp"
"./src/window/window_hook.h"
"./src/voice-input/voice_input_service.cpp"
"./src/voice-input/voice_input_service.h"
"./src/voice-input/system_audio_muter.cpp"
"./src/voice-input/system_audio_muter.h"
"./src/voice-input/doubao_asr_client.cpp"
"./src/voice-input/doubao_asr_client.h"
"./src/voice-input/voice_batch_protocol.cpp"
"./src/voice-input/voice_providers.cpp"
"./src/voice-input/voice_providers.h"
"./src/voice-input/wave_overlay.cpp"
"./src/voice-input/wave_overlay.h"
"./src/voice-input/cue_player.cpp"
"./src/voice-input/cue_player.h"
"./src/voice-input/mvi_utils.h"
"./src/voice-input/voice_input_overlay_utils.cpp"
"./src/main.cpp"
)
add_executable(${MY_EXECUTABLE_NAME} WIN32
${SRC_FILES}
)
# Tomlplusplus and other header-only libraries
target_include_directories(${PROJECT_NAME}
PRIVATE
"${CMAKE_BINARY_DIR}/vcpkg_installed/x64-windows/include"
"${CMAKE_SOURCE_DIR}/src/voice-input"
"${MSIME_ENGINE_DIR}/voice/third_party/miniaudio"
)
target_link_libraries(${PROJECT_NAME} PRIVATE MetasequoiaIme::Engine MetasequoiaIme::Voice MetasequoiaIme::VoiceCapture)
target_link_libraries(${PROJECT_NAME} PRIVATE unofficial::sqlite3::sqlite3 fmt::fmt spdlog::spdlog Boost::locale Boost::json nlohmann_json::nlohmann_json)
# U 模式候选的注音(utils/hanzi_pinyin)与设置页的导入注音共用 cpp-pinyin。
target_link_libraries(${PROJECT_NAME} PRIVATE cpp-pinyin::cpp-pinyin)
target_link_libraries(${PROJECT_NAME} PRIVATE OpenCC::OpenCC)
add_dependencies(${PROJECT_NAME} Dictionaries)
target_link_libraries(${PROJECT_NAME} PRIVATE winhttp)
target_link_libraries(${PROJECT_NAME} PRIVATE CURL::libcurl)
target_link_libraries(${PROJECT_NAME} PRIVATE ZLIB::ZLIB)
target_link_libraries(${PROJECT_NAME} PRIVATE d2d1 dwrite dwmapi shell32 shcore ole32 bcrypt)
# The helper executables below already build at /W4. The server itself -- the process that owns
# every network call and the skin loader -- was still at the default /W3.
if(MSVC)
target_compile_options(${MY_EXECUTABLE_NAME} PRIVATE /W4)
endif()
add_executable(${DICTIONARY_REPLAY_EXECUTABLE_NAME}
"./src/user-dictionary-replay/main.cpp"
"./src/resource/resource.h"
"./src/resource/resource.rc"
)
target_link_libraries(${DICTIONARY_REPLAY_EXECUTABLE_NAME} PRIVATE
MetasequoiaIme::Engine
unofficial::sqlite3::sqlite3
)
target_compile_definitions(${DICTIONARY_REPLAY_EXECUTABLE_NAME} PRIVATE NOMINMAX=1)
add_dependencies(${PROJECT_NAME} ${DICTIONARY_REPLAY_EXECUTABLE_NAME})
# msimeui stays a separately built GUI framework component at ../ui. The product-owned emoji panel
# lives under src/emoji-panel so it can evolve separately from the framework's example applications.
# msimeui's standalone layout tests belong to its own CI job. Its EXCLUDE_FROM_ALL
# targets are not built here, so registering those tests would break Server CTest.
set(_metasequoia_saved_build_testing "${BUILD_TESTING}")
set(BUILD_TESTING OFF)
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../ui" "${CMAKE_BINARY_DIR}/msimeui" EXCLUDE_FROM_ALL)
set(BUILD_TESTING "${_metasequoia_saved_build_testing}")
unset(_metasequoia_saved_build_testing)
set(EMOJI_EXECUTABLE_NAME "MetasequoiaImeEmojiPanel")
add_executable(${EMOJI_EXECUTABLE_NAME} WIN32
"./src/emoji-panel/EmojiPanel.cpp"
"./src/emoji-panel/EmojiPanel.h"
"./src/emoji-panel/emoji_panel_icons.cpp"
"./src/emoji-panel/emoji_panel_icons.h"
"./src/emoji-panel/emoji_panel_splash.cpp"
"./src/emoji-panel/emoji_panel_splash.h"
"./src/emoji-panel/svg_path_geometry.cpp"
"./src/emoji-panel/svg_path_geometry.h"
"./src/emoji-panel/main.cpp"
"./src/emoji-panel/emoji_panel.rc"
"./src/emoji-panel/resource.h"
"./src/clipboard/clipboard_history.cpp"
"./src/clipboard/clipboard_history.h"
"./src/utils/ime_paths.cpp"
"./src/utils/surface_theme_config.cpp"
"./src/utils/surface_theme_config.h"
)
add_dependencies(${MY_EXECUTABLE_NAME} ${WATCHDOG_EXECUTABLE_NAME})
target_compile_definitions(${PROJECT_NAME} PRIVATE NOMINMAX=1)
target_link_libraries(${PROJECT_NAME} PRIVATE msimeui d3d11 dxgi dcomp)
target_link_libraries(${EMOJI_EXECUTABLE_NAME} PRIVATE msimeui unofficial::sqlite3::sqlite3 shell32 advapi32 ole32)
target_compile_definitions(${EMOJI_EXECUTABLE_NAME} PRIVATE
NOMINMAX=1
WIN32_LEAN_AND_MEAN=1
)
if(MSVC)
target_compile_options(${EMOJI_EXECUTABLE_NAME} PRIVATE /W4 /permissive-)
endif()
add_dependencies(${PROJECT_NAME} ${EMOJI_EXECUTABLE_NAME})
add_custom_command(TARGET ${EMOJI_EXECUTABLE_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${CMAKE_BINARY_DIR}/vcpkg_installed/x64-windows/$<$<CONFIG:Debug>:debug/>bin/sqlite3.dll"
$<TARGET_FILE_DIR:${EMOJI_EXECUTABLE_NAME}>
)
set(KEYBOARD_EXECUTABLE_NAME "MetasequoiaImeKeyboardPanel")
add_executable(${KEYBOARD_EXECUTABLE_NAME} WIN32
"./src/keyboard-panel/KeyboardPanel.cpp"
"./src/keyboard-panel/KeyboardPanel.h"
"./src/keyboard-panel/main.cpp"
"./src/keyboard-panel/keyboard_panel.rc"
"./src/keyboard-panel/resource.h"
"./src/utils/ime_paths.cpp"
"./src/utils/surface_theme_config.cpp"
"./src/utils/surface_theme_config.h"
)
target_link_libraries(${KEYBOARD_EXECUTABLE_NAME} PRIVATE msimeui shell32 advapi32 ole32)
target_compile_definitions(${KEYBOARD_EXECUTABLE_NAME} PRIVATE
NOMINMAX=1
WIN32_LEAN_AND_MEAN=1
)
if(MSVC)
target_compile_options(${KEYBOARD_EXECUTABLE_NAME} PRIVATE /W4 /permissive-)
endif()
add_dependencies(${PROJECT_NAME} ${KEYBOARD_EXECUTABLE_NAME})
set(HANDWRITING_EXECUTABLE_NAME "MetasequoiaImeHandwritingPanel")
add_executable(${HANDWRITING_EXECUTABLE_NAME} WIN32
"./src/handwriting-panel/HandwritingPanel.cpp"
"./src/handwriting-panel/HandwritingPanel.h"
"./src/handwriting-panel/main.cpp"
"./src/handwriting-panel/handwriting_panel.rc"
"./src/handwriting-panel/resource.h"
"./src/utils/ime_paths.cpp"
"./src/utils/surface_theme_config.cpp"
"./src/utils/surface_theme_config.h"
)
target_link_libraries(${HANDWRITING_EXECUTABLE_NAME} PRIVATE msimeui windowsapp.lib shell32 advapi32 ole32)
target_compile_definitions(${HANDWRITING_EXECUTABLE_NAME} PRIVATE
NOMINMAX=1
WIN32_LEAN_AND_MEAN=1
)
if(MSVC)
target_compile_options(${HANDWRITING_EXECUTABLE_NAME} PRIVATE /W4 /permissive-)
endif()
add_dependencies(${PROJECT_NAME} ${HANDWRITING_EXECUTABLE_NAME})
set(SETTINGS_EXECUTABLE_NAME "MetasequoiaImeSettings")
add_executable(${SETTINGS_EXECUTABLE_NAME} WIN32
"./src/settings/settings_app.cpp"
"./src/ai/chat_request_params.h"
"./src/settings/api_credential_test.cpp"
"./src/settings/api_credential_test.h"
"./src/ai/ai_provider_store.cpp"
"./src/ai/ai_provider_store.h"
"./src/config/ai_provider.h"
"./src/settings/api_credential_test_request.h"
"./src/settings/collocation_model.cpp"
"./src/settings/collocation_model.h"
"./src/settings/neural_model.cpp"
"./src/settings/neural_model.h"
"./src/settings/default_input_method.cpp"
"./src/settings/default_input_method.h"
"./src/settings/game_compat_name.cpp"
"./src/settings/game_compat_name.h"
"./src/settings/settings_launcher.cpp"
"./src/settings/settings_launcher.h"
"./src/settings/native/native_settings_bindings.cpp"
"./src/settings/native/native_settings_controls.cpp"
"./src/settings/native/native_settings_controls.h"
"./src/settings/native/native_settings_model.cpp"
"./src/settings/native/native_settings_model.h"
"./src/settings/native/native_settings_pages.h"
"./src/settings/native/native_settings_theme.cpp"
"./src/settings/native/native_settings_theme.h"
"./src/settings/native/native_settings_window.cpp"
"./src/settings/native/native_settings_window.h"
"./src/settings/native/native_page_appearance.cpp"
"./src/settings/native/native_page_input.cpp"
"./src/settings/native/native_page_helpcode.cpp"
"./src/settings/native/native_page_shortcut.cpp"
"./src/settings/native/native_page_dictionary.cpp"
"./src/settings/native/native_page_dictionary_panel.cpp"
"./src/settings/native/native_page_dictionary_panel.h"
"./src/settings/native/native_page_skin.cpp"
"./src/settings/native/native_page_skin_common.cpp"
"./src/settings/native/native_page_skin_common.h"
"./src/settings/native/native_page_skin_widgets.cpp"
"./src/settings/native/native_page_voice.cpp"
"./src/settings/native/native_page_voice_fields.cpp"
"./src/settings/native/native_page_voice_fields.h"
"./src/settings/native/native_page_screenkb.cpp"
"./src/settings/native/native_page_handwriting.cpp"
"./src/settings/native/native_page_tools.cpp"
"./src/settings/native/native_page_ai.cpp"
"./src/settings/native/native_page_floating_toolbar.cpp"
"./src/settings/native/native_page_stats.cpp"
"./src/settings/native/native_page_help.cpp"
"./src/settings/native/native_page_help_widgets.cpp"
"./src/settings/native/native_page_help_widgets.h"
"./src/settings/native/native_page_about.cpp"
"./src/settings/native/native_page_feedback.cpp"
"./src/skin/candidate_skin_catalog.cpp"
"./src/skin/candidate_skin_catalog.h"
"./src/window/candidate_skin_layers.cpp"
"./src/window/candidate_skin_layers.h"
# 皮肤预览与候选窗共用同一套场景与皮肤解析,画出来的才一模一样。
"./src/window/candidate_skin_overlay.cpp"
"./src/window/candidate_skin_overlay.h"
"./src/window/candidate_skin_palette.cpp"
"./src/window/candidate_skin_palette.h"
"./src/window/candidate_skin_scene.cpp"
"./src/window/candidate_skin_scene.h"
"./src/window/candidate_skin_tokens.cpp"
"./src/window/candidate_skin_tokens.h"
"./src/window/floating_toolbar_skin.cpp"
"./src/window/floating_toolbar_skin.h"
"./src/settings/dictionary_manager.cpp"
"./src/settings/dictionary_manager.h"
"./src/settings/dictionary_validation.cpp"
"./src/settings/dictionary_validation.h"
"./src/statistics/stats_overview.cpp"
"./src/statistics/stats_overview.h"
"./src/statistics/stats_store.cpp"
"./src/statistics/stats_store.h"
"./src/config/credential_protection.cpp"
"./src/config/credential_protection.h"
"./src/config/ime_config.cpp"
"./src/config/ime_config_credentials.cpp"
"./src/config/ime_config.h"
"./src/config/ime_config_appearance.cpp"
"./src/config/ime_config_fonts.cpp"
"./src/config/ime_config_general.cpp"
"./src/config/ime_config_input.cpp"
"./src/config/ime_config_internal.h"
"./src/config/ime_config_keys.cpp"
"./src/config/ime_config_services.cpp"
"./src/config/ime_config_shuangpin.cpp"
"./src/config/ime_config_template.cpp"
"./src/config/ime_config_theme.cpp"
"./src/config/ime_config_toml.cpp"
"./src/config/ime_config_toolbar.cpp"
"./src/config/ime_config_write.cpp"
"./src/ai/chat_completions.cpp"
"./src/ai/jev_client.cpp"
"./src/ai/chat_completions.h"
"./src/cloud/ai_translation.cpp"
"./src/cloud/ai_translation.h"
"./src/cloud/custom_translation.cpp"
"./src/cloud/custom_translation.h"
"./src/cloud/niutrans_translation.cpp"
"./src/cloud/niutrans_translation.h"
"./src/cloud/tencent_tmt.cpp"
"./src/cloud/tencent_tmt.h"
"./src/cloud/translation_gloss.cpp"
"./src/cloud/translation_gloss.h"
"./src/voice-input/doubao_asr_client.cpp"
"./src/voice-input/doubao_asr_client.h"
"./src/voice-input/voice_providers.cpp"
"./src/voice-input/voice_providers.h"
"./src/clipboard/clipboard_history.cpp"
"./src/clipboard/clipboard_history.h"
"./src/utils/common_utils.cpp"
"./src/utils/common_utils.h"
"./src/utils/hanzi_pinyin.cpp"
"./src/utils/hanzi_pinyin.h"
"./src/utils/ime_paths.cpp"
"./src/utils/network_proxy.cpp"
"./src/utils/network_proxy.h"
"./src/resource/resource.rc"
)
target_include_directories(${SETTINGS_EXECUTABLE_NAME}
PRIVATE
"${CMAKE_BINARY_DIR}/vcpkg_installed/x64-windows/include"
)
target_link_libraries(${SETTINGS_EXECUTABLE_NAME} PRIVATE
msimeui
MetasequoiaIme::Engine
fmt::fmt
Boost::locale
Boost::json
nlohmann_json::nlohmann_json
unofficial::sqlite3::sqlite3
spdlog::spdlog
cpp-pinyin::cpp-pinyin
CURL::libcurl
ZLIB::ZLIB
bcrypt
winhttp
dwmapi
dcomp
d2d1
dwrite
shell32
)
if(MSVC)
target_compile_options(${SETTINGS_EXECUTABLE_NAME} PRIVATE /W4)
endif()
# The server launches the settings executable from the same output directory.
# Building the server target alone must therefore also produce Settings.
add_dependencies(${PROJECT_NAME} ${SETTINGS_EXECUTABLE_NAME})
add_custom_command(TARGET ${SETTINGS_EXECUTABLE_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${MSIME_VENDOR_DIR}/cpp-pinyin/res/dict"
"$<TARGET_FILE_DIR:${SETTINGS_EXECUTABLE_NAME}>/dict"
)
# Runtime assets next to the executable
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory
$<TARGET_FILE_DIR:${PROJECT_NAME}>/assets/audios
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_SOURCE_DIR}/assets/audios/start.mp3
${CMAKE_SOURCE_DIR}/assets/audios/end.mp3
$<TARGET_FILE_DIR:${PROJECT_NAME}>/assets/audios
COMMAND ${CMAKE_COMMAND} -E make_directory
$<TARGET_FILE_DIR:${PROJECT_NAME}>/assets/opencc
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${MSIME_VENDOR_DIR}/opencc/data/config/s2t.json
${CMAKE_BINARY_DIR}/opencc/data/CJK_Compatibility_Ideographs.ocd2
${CMAKE_BINARY_DIR}/opencc/data/STCharacters.ocd2
${CMAKE_BINARY_DIR}/opencc/data/STPhrases.ocd2
${CMAKE_BINARY_DIR}/opencc/data/STPhrases_GeneratedFromRegionalPhrases.ocd2
$<TARGET_FILE_DIR:${PROJECT_NAME}>/assets/opencc
)
if(BUILD_TESTING)
add_subdirectory(tests)
endif()