mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-03-23 04:34:39 +02:00
This feature causes nothing but problems and is frequently broken. The only optimization it was enabling were SIMD optimizations for transcoding. In particular, for UTF-16 transcoding. This is performed by the [`encoding_rs`](https://github.com/hsivonen/encoding_rs) crate, which specifically uses unstable portable SIMD APIs instead of the stable non-portable SIMD APIs. SIMD optimizations that apply to search have long been making use of stable APIs, and are automatically enabled when your target supports them. This is, IMO, the correct user experience and one that `encoding_rs` refuses to support. I'm done dealing with it, so transcoding will only use scalar code until the SIMD optimizations in `encoding_rs` work on stable. (This doesn't mean that `encoding_rs` has to change. This could also be fixed by stabilizing `std::simd`.) Fixes #2748
178 lines
5.4 KiB
Rust
178 lines
5.4 KiB
Rust
/*!
|
|
Provides routines for generating version strings.
|
|
|
|
Version strings can be just the digits, an overall short one-line description
|
|
or something more verbose that includes things like CPU target feature support.
|
|
*/
|
|
|
|
use std::fmt::Write;
|
|
|
|
/// Generates just the numerical part of the version of ripgrep.
|
|
///
|
|
/// This includes the git revision hash.
|
|
pub(crate) fn generate_digits() -> String {
|
|
let semver = option_env!("CARGO_PKG_VERSION").unwrap_or("N/A");
|
|
match option_env!("RIPGREP_BUILD_GIT_HASH") {
|
|
None => semver.to_string(),
|
|
Some(hash) => format!("{semver} (rev {hash})"),
|
|
}
|
|
}
|
|
|
|
/// Generates a short version string of the form `ripgrep x.y.z`.
|
|
pub(crate) fn generate_short() -> String {
|
|
let digits = generate_digits();
|
|
format!("ripgrep {digits}")
|
|
}
|
|
|
|
/// Generates a longer multi-line version string.
|
|
///
|
|
/// This includes not only the version of ripgrep but some other information
|
|
/// about its build. For example, SIMD support and PCRE2 support.
|
|
pub(crate) fn generate_long() -> String {
|
|
let (compile, runtime) = (compile_cpu_features(), runtime_cpu_features());
|
|
|
|
let mut out = String::new();
|
|
writeln!(out, "{}", generate_short()).unwrap();
|
|
writeln!(out).unwrap();
|
|
writeln!(out, "features:{}", features().join(",")).unwrap();
|
|
if !compile.is_empty() {
|
|
writeln!(out, "simd(compile):{}", compile.join(",")).unwrap();
|
|
}
|
|
if !runtime.is_empty() {
|
|
writeln!(out, "simd(runtime):{}", runtime.join(",")).unwrap();
|
|
}
|
|
let (pcre2_version, _) = generate_pcre2();
|
|
writeln!(out, "\n{pcre2_version}").unwrap();
|
|
out
|
|
}
|
|
|
|
/// Generates multi-line version string with PCRE2 information.
|
|
///
|
|
/// This also returns whether PCRE2 is actually available in this build of
|
|
/// ripgrep.
|
|
pub(crate) fn generate_pcre2() -> (String, bool) {
|
|
let mut out = String::new();
|
|
|
|
#[cfg(feature = "pcre2")]
|
|
{
|
|
use grep::pcre2;
|
|
|
|
let (major, minor) = pcre2::version();
|
|
write!(out, "PCRE2 {}.{} is available", major, minor).unwrap();
|
|
if cfg!(target_pointer_width = "64") && pcre2::is_jit_available() {
|
|
writeln!(out, " (JIT is available)").unwrap();
|
|
} else {
|
|
writeln!(out, " (JIT is unavailable)").unwrap();
|
|
}
|
|
(out, true)
|
|
}
|
|
|
|
#[cfg(not(feature = "pcre2"))]
|
|
{
|
|
writeln!(out, "PCRE2 is not available in this build of ripgrep.")
|
|
.unwrap();
|
|
(out, false)
|
|
}
|
|
}
|
|
|
|
/// Returns the relevant SIMD features supported by the CPU at runtime.
|
|
///
|
|
/// This is kind of a dirty violation of abstraction, since it assumes
|
|
/// knowledge about what specific SIMD features are being used by various
|
|
/// components.
|
|
fn runtime_cpu_features() -> Vec<String> {
|
|
#[cfg(target_arch = "x86_64")]
|
|
{
|
|
let mut features = vec![];
|
|
|
|
let sse2 = is_x86_feature_detected!("sse2");
|
|
features.push(format!("{sign}SSE2", sign = sign(sse2)));
|
|
|
|
let ssse3 = is_x86_feature_detected!("ssse3");
|
|
features.push(format!("{sign}SSSE3", sign = sign(ssse3)));
|
|
|
|
let avx2 = is_x86_feature_detected!("avx2");
|
|
features.push(format!("{sign}AVX2", sign = sign(avx2)));
|
|
|
|
features
|
|
}
|
|
#[cfg(target_arch = "aarch64")]
|
|
{
|
|
let mut features = vec![];
|
|
|
|
// memchr and aho-corasick only use NEON when it is available at
|
|
// compile time. This isn't strictly necessary, but NEON is supposed
|
|
// to be available for all aarch64 targets. If this isn't true, please
|
|
// file an issue at https://github.com/BurntSushi/memchr.
|
|
let neon = cfg!(target_feature = "neon");
|
|
features.push(format!("{sign}NEON", sign = sign(neon)));
|
|
|
|
features
|
|
}
|
|
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
|
|
{
|
|
vec![]
|
|
}
|
|
}
|
|
|
|
/// Returns the SIMD features supported while compiling ripgrep.
|
|
///
|
|
/// In essence, any features listed here are required to run ripgrep correctly.
|
|
///
|
|
/// This is kind of a dirty violation of abstraction, since it assumes
|
|
/// knowledge about what specific SIMD features are being used by various
|
|
/// components.
|
|
///
|
|
/// An easy way to enable everything available on your current CPU is to
|
|
/// compile ripgrep with `RUSTFLAGS="-C target-cpu=native"`. But note that
|
|
/// the binary produced by this will not be portable.
|
|
fn compile_cpu_features() -> Vec<String> {
|
|
#[cfg(target_arch = "x86_64")]
|
|
{
|
|
let mut features = vec![];
|
|
|
|
let sse2 = cfg!(target_feature = "sse2");
|
|
features.push(format!("{sign}SSE2", sign = sign(sse2)));
|
|
|
|
let ssse3 = cfg!(target_feature = "ssse3");
|
|
features.push(format!("{sign}SSSE3", sign = sign(ssse3)));
|
|
|
|
let avx2 = cfg!(target_feature = "avx2");
|
|
features.push(format!("{sign}AVX2", sign = sign(avx2)));
|
|
|
|
features
|
|
}
|
|
#[cfg(target_arch = "aarch64")]
|
|
{
|
|
let mut features = vec![];
|
|
|
|
let neon = cfg!(target_feature = "neon");
|
|
features.push(format!("{sign}NEON", sign = sign(neon)));
|
|
|
|
features
|
|
}
|
|
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
|
|
{
|
|
vec![]
|
|
}
|
|
}
|
|
|
|
/// Returns a list of "features" supported (or not) by this build of ripgrpe.
|
|
fn features() -> Vec<String> {
|
|
let mut features = vec![];
|
|
|
|
let pcre2 = cfg!(feature = "pcre2");
|
|
features.push(format!("{sign}pcre2", sign = sign(pcre2)));
|
|
|
|
features
|
|
}
|
|
|
|
/// Returns `+` when `enabled` is `true` and `-` otherwise.
|
|
fn sign(enabled: bool) -> &'static str {
|
|
if enabled {
|
|
"+"
|
|
} else {
|
|
"-"
|
|
}
|
|
}
|