Skip to content

Commit efcdae7

Browse files
authored
msrv: test aarch64 (#142)
* msrv: test aarch64 First commit should intentionally fail in CI * tweaks * version guard neon * build.rs: fix digit parsing
1 parent e73b238 commit efcdae7

File tree

3 files changed

+84
-82
lines changed

3 files changed

+84
-82
lines changed

.github/workflows/ci.yml

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ jobs:
1515
needs:
1616
- test
1717
- simd
18-
- msrv
18+
- msrv_x64
19+
- msrv_aarch64
1920
- miri
2021
steps:
2122
- run: exit 0
@@ -109,8 +110,8 @@ jobs:
109110
RUSTFLAGS: -C target_feature=${{ matrix.target_feature }}
110111
CARGO_CFG_HTTPARSE_DISABLE_SIMD_COMPILETIME: ${{ matrix.disable_compiletime }}
111112

112-
msrv:
113-
name: msrv
113+
msrv_x64:
114+
name: msrv (x64)
114115
runs-on: ubuntu-latest
115116
steps:
116117
- name: Checkout
@@ -123,12 +124,40 @@ jobs:
123124
toolchain: 1.36.0
124125
override: true
125126

126-
# Only build, dev-dependencies don't compile on 1.10
127+
# Only build, dev-dependencies don't compile on 1.36.0
127128
- name: Build
128129
uses: actions-rs/cargo@v1
129130
with:
130131
command: build
131132

133+
# This tests that aarch64 gracefully fallbacks to SWAR if neon_intrinsics aren't available (<1.59)
134+
msrv_aarch64:
135+
name: msrv (aarch64)
136+
runs-on: ubuntu-latest
137+
steps:
138+
- name: Checkout
139+
uses: actions/checkout@v1
140+
141+
- name: Install cross-compiling dependencies
142+
run: |
143+
sudo apt-get update
144+
sudo apt-get install -y gcc-aarch64-linux-gnu
145+
146+
- name: Setup Rust
147+
uses: actions-rs/toolchain@v1
148+
with:
149+
profile: minimal
150+
toolchain: 1.36.0
151+
override: true
152+
target: aarch64-unknown-linux-gnu
153+
154+
# Only build, dev-dependencies don't compile on 1.36.0
155+
- name: Build
156+
uses: actions-rs/cargo@v1
157+
with:
158+
command: build
159+
args: --target aarch64-unknown-linux-gnu
160+
132161
miri:
133162
name: Test with Miri
134163
runs-on: ubuntu-latest

build.rs

Lines changed: 45 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,36 @@
11
use std::env;
2-
//use std::ffi::OsString;
3-
//use std::process::Command;
2+
use std::ffi::OsString;
3+
use std::process::Command;
44

55
fn main() {
6-
// We don't currently need to check the Version anymore...
7-
// But leaving this in place in case we need to in the future.
8-
/*
6+
// We check rustc version to enable features beyond MSRV, such as:
7+
// - 1.59 => neon_intrinsics
98
let rustc = env::var_os("RUSTC").unwrap_or(OsString::from("rustc"));
109
let output = Command::new(&rustc)
1110
.arg("--version")
1211
.output()
1312
.expect("failed to check 'rustc --version'")
1413
.stdout;
1514

16-
let version = String::from_utf8(output)
15+
let raw_version = String::from_utf8(output)
1716
.expect("rustc version output should be utf-8");
18-
*/
19-
20-
enable_new_features(/*&version*/);
21-
}
22-
23-
fn enable_new_features(/*raw_version: &str*/) {
24-
/*
25-
let version = match Version::parse(raw_version) {
17+
18+
let version = match Version::parse(&raw_version) {
2619
Ok(version) => version,
2720
Err(err) => {
2821
println!("cargo:warning=failed to parse `rustc --version`: {}", err);
2922
return;
3023
}
3124
};
32-
*/
3325

34-
enable_simd(/*version*/);
26+
enable_new_features(version);
3527
}
3628

37-
fn enable_simd(/*version: Version*/) {
29+
fn enable_new_features(version: Version) {
30+
enable_simd(version);
31+
}
32+
33+
fn enable_simd(version: Version) {
3834
if env::var_os("CARGO_FEATURE_STD").is_none() {
3935
println!("cargo:warning=building for no_std disables httparse SIMD");
4036
return;
@@ -50,6 +46,11 @@ fn enable_simd(/*version: Version*/) {
5046
return;
5147
}
5248

49+
// 1.59.0 is the first version to support neon_intrinsics
50+
if version >= Version(1, 59, 0) {
51+
println!("cargo:rustc-cfg=httparse_simd_neon_intrinsics");
52+
}
53+
5354
println!("cargo:rustc-cfg=httparse_simd");
5455

5556
// cfg(target_feature) isn't stable yet, but CARGO_CFG_TARGET_FEATURE has
@@ -83,79 +84,46 @@ fn enable_simd(/*version: Version*/) {
8384
return
8485
},
8586
};
86-
87-
let mut saw_sse42 = false;
88-
let mut saw_avx2 = false;
89-
90-
for feature in feature_list.split(',') {
91-
let feature = feature.trim();
92-
if !saw_sse42 && feature == "sse4.2" {
93-
saw_sse42 = true;
94-
println!("cargo:rustc-cfg=httparse_simd_target_feature_sse42");
95-
}
96-
97-
if !saw_avx2 && feature == "avx2" {
98-
saw_avx2 = true;
99-
println!("cargo:rustc-cfg=httparse_simd_target_feature_avx2");
100-
}
87+
88+
let features = feature_list.split(',').map(|s| s.trim());
89+
if features.clone().any(|f| f == "sse4.2") {
90+
println!("cargo:rustc-cfg=httparse_simd_target_feature_sse42");
91+
}
92+
if features.clone().any(|f| f == "avx2") {
93+
println!("cargo:rustc-cfg=httparse_simd_target_feature_avx2");
10194
}
10295
}
10396

104-
/*
10597
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
106-
struct Version {
107-
major: u32,
108-
minor: u32,
109-
patch: u32,
110-
}
98+
struct Version (u32, u32, u32);
11199

112100
impl Version {
113-
fn parse(mut s: &str) -> Result<Version, String> {
101+
fn parse(s: &str) -> Result<Version, String> {
114102
if !s.starts_with("rustc ") {
115103
return Err(format!("unrecognized version string: {}", s));
116104
}
117-
s = &s["rustc ".len()..];
118-
119-
let parts: Vec<&str> = s.split(".").collect();
120-
if parts.len() < 3 {
121-
return Err(format!("not enough version parts: {:?}", parts));
122-
}
123-
124-
let mut num = String::new();
125-
for c in parts[0].chars() {
126-
if !c.is_digit(10) {
127-
break;
128-
}
129-
num.push(c);
130-
}
131-
let major = num.parse::<u32>().map_err(|e| e.to_string())?;
132-
133-
num.clear();
134-
for c in parts[1].chars() {
135-
if !c.is_digit(10) {
136-
break;
137-
}
138-
num.push(c);
139-
}
140-
let minor = num.parse::<u32>().map_err(|e| e.to_string())?;
141-
142-
num.clear();
143-
for c in parts[2].chars() {
144-
if !c.is_digit(10) {
145-
break;
146-
}
147-
num.push(c);
105+
let s = s.trim_start_matches("rustc ");
106+
107+
let mut iter = s
108+
.split(".")
109+
.take(3)
110+
.map(|s| match s.find(|c: char| !c.is_ascii_digit()) {
111+
Some(end) => &s[..end],
112+
None => s,
113+
})
114+
.map(|s| s.parse::<u32>().map_err(|e| e.to_string()));
115+
116+
if iter.clone().count() != 3 {
117+
return Err(format!("not enough version parts: {:?}", s));
148118
}
149-
let patch = num.parse::<u32>().map_err(|e| e.to_string())?;
119+
120+
let major = iter.next().unwrap()?;
121+
let minor = iter.next().unwrap()?;
122+
let patch = iter.next().unwrap()?;
150123

151-
Ok(Version {
152-
major: major,
153-
minor: minor,
154-
patch: patch,
155-
})
124+
Ok(Version(major, minor, patch))
156125
}
157126
}
158-
*/
159127

160128
fn var_is(key: &str, val: &str) -> bool {
161129
match env::var(key) {

src/simd/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ mod swar;
55
any(
66
target_arch = "x86",
77
target_arch = "x86_64",
8-
target_arch = "aarch64",
8+
all(
9+
target_arch = "aarch64",
10+
httparse_simd_neon_intrinsics,
11+
)
912
),
1013
)))]
1114
pub use self::swar::*;
@@ -137,11 +140,13 @@ pub use self::avx2_compile_time::*;
137140
#[cfg(all(
138141
httparse_simd,
139142
target_arch = "aarch64",
143+
httparse_simd_neon_intrinsics,
140144
))]
141145
mod neon;
142146

143147
#[cfg(all(
144148
httparse_simd,
145149
target_arch = "aarch64",
150+
httparse_simd_neon_intrinsics,
146151
))]
147152
pub use self::neon::*;

0 commit comments

Comments
 (0)