hyperscan_src/lib.rs
1//! hyperscan-src: 将 intel/hyperscan C++ 源码打包为 Rust crate,通过 cmake 从源码编译。
2//!
3//! # 设计原理
4//!
5//! 本 crate 使用 **openssl-src 模式**:cmake 调用放在 `lib.rs` 而非 `build.rs`。
6//! 原因:将 cmake 调用放入 lib.rs 后,下游 crate(hypervectorscan-sys)在其 `build.rs`
7//! 中通过函数调用执行。此时所有 `cargo:rustc-link-*` 指令都在 hypervectorscan-sys 的
8//! build script 进程内发出 → Cargo 能正确将这些链接指令应用到最终产物。
9//!
10//! 如果放在本 crate 的 build.rs,link 指令会因为 crate 间隔离而无法传递到最终二进制。
11//!
12//! # 系统依赖
13//!
14//! 编译本 crate 需要:
15//! - cmake ≥ 3.x
16//! - C++ 编译器(gcc / clang)
17//! - ragel
18//! - boost-dev
19//!
20//! 这些依赖仅在启用 `vendored` feature 时需要。缺少时 cmake 的 configure 阶段会报错,
21//! 错误信息会通过 cargo 输出清晰的提示。
22
23use std::path::PathBuf;
24
25/// 构建配置
26pub struct Build {
27 fat_runtime: bool,
28 build_avx512: bool,
29 build_avx512vbmi: bool,
30}
31
32/// 构建产物路径信息
33pub struct Artifacts {
34 /// 头文件目录(包含 hs/hs.h)
35 pub include_dir: PathBuf,
36 /// 库文件目录(libhs.a, libhs_runtime.a)
37 pub lib_dir: PathBuf,
38 /// 链接的库名列表
39 pub libs: Vec<String>,
40}
41
42impl Build {
43 /// 创建默认构建配置。
44 ///
45 /// 默认启用 FAT_RUNTIME(运行时 CPU 特性检测),避免在不支持 AVX-512 的 CPU 上
46 /// 因预编译二进制包含 AVX-512 指令而导致 SIGILL。
47 pub fn new() -> Self {
48 Build {
49 fat_runtime: true,
50 build_avx512: false,
51 build_avx512vbmi: false,
52 }
53 }
54
55 /// 启用/禁用 FAT_RUNTIME(运行时 CPU 分发,默认启用)
56 pub fn fat_runtime(&mut self, v: bool) -> &mut Self {
57 self.fat_runtime = v;
58 self
59 }
60 /// 启用 AVX512 指令集支持(x86_64 可选)
61 pub fn avx512(&mut self, v: bool) -> &mut Self {
62 self.build_avx512 = v;
63 self
64 }
65 /// 启用 AVX512VBMI 指令集支持(x86_64 可选,依赖 BUILD_AVX512)
66 pub fn avxvnni(&mut self, v: bool) -> &mut Self {
67 self.build_avx512vbmi = v;
68 self
69 }
70
71 /// 执行 cmake 构建,编译 Hyperscan 静态库。
72 ///
73 /// 此函数内部:
74 /// 1. 调用 `cmake::Config::new("hyperscan")` 配置构建
75 /// 2. 设置必要的 cmake flags(静态库、Release、FAT_RUNTIME 等)
76 /// 3. 调用 `config.build()` 执行编译+安装
77 /// 4. 通过 `println!("cargo:rustc-link-*")` 输出链接指令
78 /// (这些指令由调用者进程发出,因此能正确应用到最终二进制)
79 /// 5. 返回包含头文件/库文件路径的 Artifacts
80 pub fn build(&mut self) -> Artifacts {
81 println!(
82 "cargo:warning=Vendored Hyperscan build — requires: cmake, C++ compiler, ragel, boost-dev"
83 );
84 let source_dir = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("hyperscan");
85 let mut config = cmake::Config::new(source_dir);
86 config
87 .define("BUILD_STATIC_LIBS", "ON")
88 .define("BUILD_SHARED_LIBS", "OFF")
89 .define("CMAKE_BUILD_TYPE", "Release")
90 .define("BUILD_UNIT", "OFF")
91 .define("BUILD_EXAMPLES", "OFF")
92 .define("BUILD_BENCHMARKS", "OFF");
93
94 if self.fat_runtime {
95 config.define("FAT_RUNTIME", "ON");
96 }
97 if self.build_avx512 {
98 config.define("BUILD_AVX512", "ON");
99 }
100 if self.build_avx512vbmi {
101 config.define("BUILD_AVX512VBMI", "ON");
102 }
103
104 let dst = config.build();
105
106 let lib_dir = dst.join("lib");
107 println!("cargo:rustc-link-search=native={}", lib_dir.display());
108 println!("cargo:rustc-link-lib=static=hs");
109 println!("cargo:rustc-link-lib=static=hs_runtime");
110
111 Artifacts {
112 include_dir: dst.join("include"),
113 lib_dir,
114 libs: vec!["hs".into(), "hs_runtime".into()],
115 }
116 }
117}