111 lines
6.6 KiB
CMake
111 lines
6.6 KiB
CMake
# kenlm 查询子集 + 本仓的语言模型封装。
|
||
#
|
||
# 只编译 kenlm 的 query / trie-build 路径:lm/ 与 util/ 的顶层源文件,外加
|
||
# util/double-conversion。lm/builder、lm/filter、lm/interpolate、lm/wrappers
|
||
# 没有复制进来,顶层源文件也不 include 它们。
|
||
#
|
||
# 不要定义 WITH_THREADS。定义之后 util/parallel_read.cc 会走 thread_pool.hh
|
||
# 那条分支,从而拖进 boost::thread 这个需要编译的库;不定义时它退化成串行的
|
||
# ErsatzPRead,整个子集因此是零 Boost 依赖的。
|
||
#
|
||
# KENLM_MAX_ORDER 必须与生成 .lm 时使用的值一致。libime 用的是 3,出货的
|
||
# sc.lm 也是三元模型,改这里等于让运行时读不懂已经发布的模型文件。
|
||
#
|
||
# language_model.cpp 故意编进同一个目标:它是唯一 include kenlm 头文件的地方。
|
||
# 这样 _HAS_AUTO_PTR_ETC 和 kenlm 的 include 目录都能保持 PRIVATE,engine 的
|
||
# 其余部分只看得到 language_model.h 这个纯 std 的头。
|
||
|
||
# 这个目录既被 engine/ 和 engine/tests/ 用 add_subdirectory 挂进去,也可以单独
|
||
# configure —— scripts/build-language-model.ps1 就是这么用的:它只要 ARPA -> .lm
|
||
# 那个工具,不该为了 engine 依赖的 SQLite 去拉起 vcpkg。作为子目录时下面这段不执行,
|
||
# 顶层工程的 C++ 标准和策略照旧由父目录决定。
|
||
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
|
||
cmake_minimum_required(VERSION 3.20)
|
||
project(metasequoia_ime_ngram_tools CXX)
|
||
set(CMAKE_CXX_STANDARD 17)
|
||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||
endif()
|
||
|
||
# kenlm 全程用窄字符调 Win32(util/file.cc 里的 GetTempPath 就收一个 char[]),
|
||
# 所以这里必须在 UNICODE/_UNICODE 之外编。add_subdirectory 会继承父目录用
|
||
# add_definitions 设的宏,engine/tests/CMakeLists.txt 正好就是这么定义 UNICODE 的,
|
||
# 于是 GetTempPath 解析成 GetTempPathW 而编不过。清掉本目录继承来的那一份;
|
||
# 引擎自己那套 PUBLIC 的 UNICODE 走的是 target_compile_definitions,不经过这里。
|
||
set_directory_properties(PROPERTIES COMPILE_DEFINITIONS "")
|
||
|
||
file(GLOB METASEQUOIA_IME_KENLM_SOURCES
|
||
"${CMAKE_CURRENT_SOURCE_DIR}/kenlm/lm/*.cc"
|
||
"${CMAKE_CURRENT_SOURCE_DIR}/kenlm/util/*.cc"
|
||
"${CMAKE_CURRENT_SOURCE_DIR}/kenlm/util/double-conversion/*.cc")
|
||
# *_main.cc 带 main(),是工具的入口而不是库的一部分。它们留在上游布局里,
|
||
# 因为其中的 #include "model.hh" 是相对自身目录解析的,挪走就编不过。
|
||
list(FILTER METASEQUOIA_IME_KENLM_SOURCES EXCLUDE REGEX "_main\\.cc$")
|
||
|
||
add_library(metasequoia_ime_ngram STATIC
|
||
${METASEQUOIA_IME_KENLM_SOURCES}
|
||
"${CMAKE_CURRENT_SOURCE_DIR}/language_model.cpp"
|
||
# 万象语法模型(octagram .gram)的读取端,与 kenlm 同库:它和语言模型封装
|
||
# 一样是「引擎其余部分只看头文件」的独立模块,Win32 mmap 的实现细节留在 cpp 里。
|
||
"${CMAKE_CURRENT_SOURCE_DIR}/octagram/octagram_gram.cpp")
|
||
|
||
# PUBLIC 指向仓库根,这样调用方按 AGENTS.md 的约定写
|
||
# #include "engine/ngram/language_model.h"。kenlm 的头保持 PRIVATE。
|
||
target_include_directories(metasequoia_ime_ngram
|
||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../.."
|
||
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/kenlm")
|
||
|
||
# octagram 的头(含第三方 darts.h)按外部头暴露:darts.h 有一批 MSVC size_t 收窄
|
||
# 告警(C4267),会随引擎头在每个消费方的编译单元里重复报一遍——引擎库自己有 /wd
|
||
# 兜底,服务器端没有。SYSTEM 让 MSVC 走 /external:I、类 Unix 编译器走 -isystem,
|
||
# 告警在消费方被抑制;移植代码 octagram_gram.* 不吃亏,本目标的 /wd 已覆盖同类告警。
|
||
target_include_directories(metasequoia_ime_ngram
|
||
SYSTEM PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/octagram")
|
||
target_compile_definitions(metasequoia_ime_ngram PRIVATE KENLM_MAX_ORDER=3)
|
||
set_target_properties(metasequoia_ime_ngram PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||
|
||
if(MSVC)
|
||
# kenlm 仍在用 C++17 移除的 std::binary_function(trie_sort.hh、
|
||
# sized_iterator.hh、joint_sort.hh)。_HAS_AUTO_PTR_ETC 把这批符号加回来,
|
||
# 这是 MSVC 侧对应 libime 给 libc++ 加的
|
||
# _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION。
|
||
# 它只恢复符号、不改变既有代码行为,且保持 PRIVATE 不外泄。
|
||
target_compile_definitions(metasequoia_ime_ngram PRIVATE
|
||
_HAS_AUTO_PTR_ETC=1 NOMINMAX _CRT_SECURE_NO_WARNINGS)
|
||
# 上游副本,不为它改代码风格,也不逐个修收窄转换告警。
|
||
target_compile_options(metasequoia_ime_ngram PRIVATE /utf-8 /wd4244 /wd4267 /wd4996 /wd4018 /wd4334)
|
||
endif()
|
||
|
||
# kenlm 的 _open 走 ANSI 代码页,本仓的路径是 UTF-8。强制包含一个只声明
|
||
# util::_open 重载的头把它接到宽字符 API 上,不改上游源码。理由见该头文件。
|
||
if(WIN32)
|
||
if(MSVC)
|
||
set(METASEQUOIA_IME_KENLM_FILE_IO_OPTIONS "/FI${CMAKE_CURRENT_SOURCE_DIR}/kenlm_file_io.h")
|
||
else()
|
||
set(METASEQUOIA_IME_KENLM_FILE_IO_OPTIONS -include "${CMAKE_CURRENT_SOURCE_DIR}/kenlm_file_io.h")
|
||
endif()
|
||
set_property(SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/kenlm/util/file.cc"
|
||
APPEND PROPERTY COMPILE_OPTIONS ${METASEQUOIA_IME_KENLM_FILE_IO_OPTIONS})
|
||
endif()
|
||
|
||
# 把 ARPA 转成出货的 sc.lm 的工具。默认不建:它只在重新生成模型数据时才需要,
|
||
# 产品构建不依赖它。开启方式见 README.md 的"重新生成语言模型"。
|
||
option(METASEQUOIA_IME_BUILD_NGRAM_TOOLS "Build the ARPA -> .lm conversion tool" OFF)
|
||
if(METASEQUOIA_IME_BUILD_NGRAM_TOOLS)
|
||
# getopt.c 是 kenlm 自带的 Windows 移植(MSVC 的 CRT 没有 getopt),只有
|
||
# 工具入口用得到,库本身不需要,所以不进上面那个 glob。
|
||
# 它必须按 C 编译:getopt.hh 用 extern "C" 声明这些符号。enable_language 放在
|
||
# 这个默认关闭的分支里,产品构建因此仍然是纯 CXX 工程。
|
||
enable_language(C)
|
||
add_executable(metasequoia_ime_build_binary
|
||
"${CMAKE_CURRENT_SOURCE_DIR}/kenlm/lm/build_binary_main.cc"
|
||
"${CMAKE_CURRENT_SOURCE_DIR}/kenlm/util/getopt.c")
|
||
target_link_libraries(metasequoia_ime_build_binary PRIVATE metasequoia_ime_ngram)
|
||
target_include_directories(metasequoia_ime_build_binary PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/kenlm")
|
||
target_compile_definitions(metasequoia_ime_build_binary PRIVATE KENLM_MAX_ORDER=3)
|
||
if(MSVC)
|
||
target_compile_definitions(metasequoia_ime_build_binary PRIVATE
|
||
_HAS_AUTO_PTR_ETC=1 NOMINMAX _CRT_SECURE_NO_WARNINGS)
|
||
target_compile_options(metasequoia_ime_build_binary PRIVATE /wd4244 /wd4267 /wd4996)
|
||
endif()
|
||
endif()
|