在Windows上编译pg_jieba扩展前,需要先搭建完整的开发环境。我建议使用Visual Studio 2019或更高版本,因为它在CMake支持和C++标准兼容性方面表现最好。实测发现VS2022也能正常工作,但需要额外注意SDK版本匹配问题。
首先安装这些必备组件:
源码获取有个小技巧:不要直接克隆到Program Files这类有空格和权限限制的目录。我习惯在D盘创建build目录专门存放编译项目:
bash复制mkdir D:\build
cd D:\build
git clone https://github.com/jaiminpan/pg_jieba
git clone --depth=1 https://github.com/yanyiwu/cppjieba.git
这里使用--depth=1参数可以大幅减少下载时间,因为cppjieba的提交历史很长。克隆完成后需要手动整理依赖文件:
这个步骤很多人会漏掉,导致后续编译时报找不到头文件的错误。我建议用xcopy命令处理:
cmd复制xcopy /E /I cppjieba\deps pg_jieba\libjieba\deps
xcopy /E /I cppjieba\include pg_jieba\libjieba\include
xcopy /E /I cppjieba\dict pg_jieba\libjieba\dict
原始代码需要几处调整才能在Windows上顺利编译。第一个要修改的是jieba_token.h文件,主要去掉结构体初始化时的字段名:
c复制// 修改前
static const TokenDescData lex_descr[] = {
{ .token = "", .descr = ""},
{ .token = "eng", .descr = "letter"}
};
// 修改后
static const TokenDescData lex_descr[] = {
{ "", ""},
{ "eng", "letter"}
};
这种语法差异是因为MSVC编译器对C99风格的指定初始化器支持不完全。修改后记得保存文件,否则会导致编译时报"expected identifier"错误。
第二个关键修改是添加pg_main.h头文件。这个文件主要声明了PostgreSQL扩展的入口函数:
c复制#ifndef PG_MAIN_H
#define PG_MAIN_H
#include <postgres.h>
#include <fmgr.h>
PGDLLEXPORT void _PG_init(void);
PGDLLEXPORT void _PG_fini(void);
PGDLLEXPORT Datum jieba_start(PG_FUNCTION_ARGS);
/* 其他函数声明... */
#endif
然后在pg_jieba.c中引入这个头文件,并注释掉原有的函数声明。这一步很多人会忽略顺序问题,正确的做法是在包含其他PostgreSQL头文件之后引入:
c复制#include "postgres.h"
#include "fmgr.h"
#include "pg_main.h" // 必须放在标准头文件之后
/* 注释掉原有的函数声明
Datum jieba_start(PG_FUNCTION_ARGS);
*/
Windows下的CMake配置需要特殊处理。打开pg_jieba目录下的CMakeLists.txt,在开头添加版本声明:
cmake复制cmake_minimum_required(VERSION 3.11)
接着在message(STATUS "Setting ${CMAKE_PROJECT_NAME}...")后面添加MSVC专用配置:
cmake复制if(MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
add_definitions(-D_HAS_AUTO_PTR_ETC=1)
set(PostgreSQL_INCLUDE_DIR "C:/pgsql/include/server/port/win32_msvc;C:/pgsql/include/server/port/win32")
set(PostgreSQL_PG_CONFIG "C:/pgsql/bin/pg_config.exe")
set(PostgreSQL_LIBRARY "C:/pgsql/lib/postgres.lib")
endif()
这里有个坑点:路径必须使用正斜杠且不能有空格。如果PostgreSQL安装在Program Files下,建议重装到简单路径如C:\pgsql。
最后在add_library语句后添加链接库指令:
cmake复制target_link_libraries(${PG_JIEBA_LIBRARY_NAME} ${PostgreSQL_LIBRARY})
启动"x64 Native Tools Command Prompt"后,按步骤执行:
cmd复制rd /S /Q vc_build
cmake-gui -Wno-dev -DCMAKE_BUILD_TYPE=Release -B vc_build -S .
在CMake GUI中:
关键步骤来了:用文本编辑器打开vc_build\pg_jieba.vcxproj,搜索并删除所有"没有被记录"字符串。这个奇怪的问题是由于pg_config输出格式导致的。
然后用Visual Studio打开vc_build目录下的解决方案:
安装后需要重命名DLL文件:
cmd复制del C:\pgsql\lib\pg_jieba.dll
rename C:\pgsql\lib\libpg_jieba.dll pg_jieba.dll
可以用dumpbin检查依赖是否完整:
cmd复制dumpbin /DEPENDENTS C:\pgsql\lib\pg_jieba.dll
正常应该看到postgres.dll、msvcr120.dll等依赖项。如果报缺少DLL,需要安装对应的VC++运行库。
编译生成的文件主要分为三类:
核心组件:
词典数据:
开发文件:
修改postgresql.conf启用扩展:
ini复制shared_preload_libraries = 'pg_jieba'
重启服务后测试:
sql复制CREATE EXTENSION pg_jieba;
SELECT * FROM to_tsquery('jiebacfg', '自然语言处理真有趣');
如果遇到词典加载失败,可以执行SELECT jieba_reload_dict();重新加载,无需重启服务。
编译时报LNK2001错误:
通常是链接库路径问题。检查:
运行时找不到分词结果:
大概率是词典路径问题。检查:
扩展加载失败:
查看PostgreSQL日志,常见原因:
通过多次测试,我发现几个有效的优化点:
init_jieba_dict函数,添加预加载逻辑:c复制Jieba_LoadDict(jieba, dict_path, 1); // 最后一个参数启用内存缓存
ini复制pg_jieba.parallel_mode = on
pg_jieba.thread_num = 4 # 根据CPU核心数调整
自定义词典策略:
将高频专业术语添加到jieba_user.dict,格式为:
code复制云计算 3 n
大数据 3 n
数字表示词频权重,n是词性标记。
停用词过滤:
在jieba.stop中添加无意义的助词、标点等,可以提升查询效率。