Skip to main content

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}