vectorscan_src/lib.rs
1//! vectorscan-src: 将 VectorCamp/vectorscan C++ 源码打包为 Rust crate,通过 cmake 从源码编译。
2//!
3//! Vectorscan 是 Intel Hyperscan 的可移植分支,支持 ARM NEON/SVE2、Power VSX 等架构。
4//! 在 ARM64 平台上,hypervectorscan-sys 使用本 crate 而非 hyperscan-src。
5//!
6//! # 设计原理
7//!
8//! 同 hyperscan-src:cmake 调用放在 lib.rs(非 build.rs),使 link 指令在下游 crate
9//! 的 build script 进程内发出,保证正确传递到最终产物。
10//!
11//! # 系统依赖
12//!
13//! 编译本 crate 需要:
14//! - cmake ≥ 3.x
15//! - C++ 编译器(gcc / clang)
16//! - ragel
17//! - boost-dev
18//!
19//! SIMDe 后端(BUILD_SIMDE_BACKEND)默认关闭,不影响构建。
20
21use std::path::PathBuf;
22
23/// 构建配置
24pub struct Build {
25 fat_runtime: bool,
26}
27
28/// 构建产物路径信息
29pub struct Artifacts {
30 /// 头文件目录(包含 hs/hs.h)
31 pub include_dir: PathBuf,
32 /// 库文件目录(libhs.a, libhs_runtime.a)
33 pub lib_dir: PathBuf,
34 /// 链接的库名列表
35 pub libs: Vec<String>,
36}
37
38impl Build {
39 /// 创建默认构建配置。
40 ///
41 /// 默认启用 FAT_RUNTIME(ARM ASIMD/SVE/SVE2 运行时分发),
42 /// 禁用 USE_CPU_NATIVE(避免绑定到编译机器的 CPU 特性)。
43 pub fn new() -> Self {
44 Build { fat_runtime: true }
45 }
46
47 /// 启用/禁用 FAT_RUNTIME(运行时 CPU 分发,ARM 平台默认启用)
48 pub fn fat_runtime(&mut self, v: bool) -> &mut Self {
49 self.fat_runtime = v;
50 self
51 }
52
53 /// 执行 cmake 构建,编译 Vectorscan 静态库。
54 ///
55 /// cmake flags:
56 /// - BUILD_STATIC_LIBS=ON: 编译静态库
57 /// - FAT_RUNTIME=ON: ARM 运行时 CPU 特性调度
58 /// - USE_CPU_NATIVE=OFF: 不针对编译机器 CPU 优化(保证跨机型可移植)
59 /// - BUILD_UNIT=OFF: 跳过单元测试编译
60 /// - BUILD_SIMDE_BACKEND 保持默认 OFF(ARM 使用 NEON/SVE2 原生后端)
61 pub fn build(&mut self) -> Artifacts {
62 println!(
63 "cargo:warning=Vendored Vectorscan build — requires: cmake, C++ compiler, ragel, boost-dev"
64 );
65 let source_dir = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("vectorscan");
66 let mut config = cmake::Config::new(source_dir);
67 config
68 .define("BUILD_STATIC_LIBS", "ON")
69 .define("BUILD_SHARED_LIBS", "OFF")
70 .define("CMAKE_BUILD_TYPE", "Release")
71 .define("CMAKE_INSTALL_LIBDIR", "lib")
72 .define("BUILD_UNIT", "OFF")
73 .define("BUILD_TOOLS", "OFF")
74 .define("BUILD_EXAMPLES", "OFF")
75 .define("BUILD_DOC", "OFF")
76 .define("BUILD_BENCHMARKS", "OFF")
77 .define("USE_CPU_NATIVE", "OFF");
78
79 if self.fat_runtime {
80 config.define("FAT_RUNTIME", "ON");
81 }
82
83 let dst = config.build();
84
85 // Some cmake versions install to lib64 or multiarch paths;
86 // search lib/, lib64/, lib/<arch>-linux-gnu/ — first containing libhs.a wins.
87 let lib_dir = {
88 let candidates: Vec<PathBuf> = vec![
89 dst.join("lib"),
90 dst.join("lib64"),
91 dst.join(format!("lib/{}-linux-gnu", std::env::consts::ARCH)),
92 ];
93 candidates
94 .into_iter()
95 .find(|d| d.join("libhs.a").exists())
96 .unwrap_or_else(|| dst.join("lib"))
97 };
98
99 println!("cargo:rustc-link-search=native={}", lib_dir.display());
100 println!("cargo:rustc-link-lib=static=hs");
101 println!("cargo:rustc-link-lib=static=hs_runtime");
102
103 Artifacts {
104 include_dir: dst.join("include"),
105 lib_dir,
106 libs: vec!["hs".into(), "hs_runtime".into()],
107 }
108 }
109}