Skip to content

Commit 70820b1

Browse files
committed
feat: set clang version min and max at compile time
This adds a build script that downloads versions.json from `cpp-linter/clang-tools-static-binaries` latest release and injects it into the production code using compile-time-only environment variables. Includes a similar adjustment to the test CI job in some inline nu shell script that employs gh-cli instead of direct download.
1 parent 701217d commit 70820b1

6 files changed

Lines changed: 77 additions & 27 deletions

File tree

.github/workflows/run-dev-tests.yml

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,23 @@ jobs:
9999
uses: hustcer/setup-nu@92c296ba1ba2ba04cc948ab64ddefe192dc13f0c # v3.23
100100

101101
- name: Run test suite
102-
env:
103-
MIN_CLANG_TOOLS_VERSION: "11"
104-
MAX_CLANG_TOOLS_VERSION: "22"
105102
shell: nu {0}
106103
run: |-
107-
let max_ver = $env.MAX_CLANG_TOOLS_VERSION | into int
108-
let min_ver = $env.MIN_CLANG_TOOLS_VERSION | into int
104+
let version_info = (
105+
(^gh release download -R cpp-linter/clang-tools-static-binaries --pattern versions.json --output -)
106+
| from json
107+
)
108+
mut max_ver = 0
109+
mut min_ver = 99
110+
for ver in ($version_info.llvm_versions | columns) {
111+
let ver = $ver | into int
112+
if ($ver < $min_ver) {
113+
$min_ver = $ver
114+
}
115+
if ($ver > $max_ver) {
116+
$max_ver = $ver
117+
}
118+
}
109119
for $ver in ($min_ver..$max_ver) {
110120
print $"::group::Testing with clang v($ver)"
111121
with-env { CLANG_VERSION: $"($ver)" } {

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,3 +347,4 @@ cpp-linter-py/docs/cli_args.rst
347347
lcov.info
348348
coverage.json
349349
.config/ReleaseNotes.md
350+
versions.json

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

clang-installer/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,10 @@ tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
4747
[features]
4848
bin = ["dep:clap", "dep:tokio", "dep:anyhow", "dep:colored"]
4949

50+
[build-dependencies]
51+
serde = { workspace = true }
52+
serde_json = { workspace = true }
53+
reqwest = { workspace = true, features = ["default-tls", "blocking"] }
54+
5055
[package.metadata.binstall]
5156
pkg-url = "{ repo }/releases/download/clang-installer/v{ version }/{ name }-{ target }{ archive-suffix }"

clang-installer/build.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use std::{fs, path::PathBuf, time::Duration};
2+
3+
use reqwest::blocking::ClientBuilder;
4+
5+
const URL: &str = "https://github.com/cpp-linter/clang-tools-static-binaries/releases/latest/download/versions.json";
6+
7+
#[derive(Debug, serde::Deserialize)]
8+
struct VersionInfo {
9+
release_tag: String,
10+
llvm_versions: std::collections::HashMap<u8, String>,
11+
}
12+
fn main() {
13+
let pre_seed = PathBuf::from("versions.json");
14+
let version_info_str = if pre_seed.exists() {
15+
println!("cargo:warning=Using pre-seeded version info from {pre_seed:?}");
16+
fs::read_to_string(&pre_seed).unwrap()
17+
} else {
18+
ClientBuilder::new()
19+
.user_agent("cpp-linter-rs/clang-installer")
20+
.timeout(Duration::from_secs(30))
21+
.build()
22+
.unwrap()
23+
.get(URL)
24+
.send()
25+
.unwrap()
26+
.text()
27+
.unwrap()
28+
};
29+
let version_info: VersionInfo = serde_json::from_str(&version_info_str).unwrap();
30+
let (min_ver, max_ver) = {
31+
let (mut min_v, mut max_v) = (None, None);
32+
for ver in version_info.llvm_versions.keys() {
33+
if min_v.is_none_or(|v| v > ver) {
34+
min_v = Some(ver);
35+
}
36+
if max_v.is_none_or(|v| v < ver) {
37+
max_v = Some(ver);
38+
}
39+
}
40+
(min_v.unwrap(), max_v.unwrap())
41+
};
42+
println!(
43+
"cargo:rustc-env=CLANG_TOOLS_TAG={}",
44+
version_info.release_tag
45+
);
46+
println!("cargo:rustc-env=MIN_CLANG_TOOLS_VERSION={min_ver}");
47+
println!("cargo:rustc-env=MAX_CLANG_TOOLS_VERSION={max_ver}");
48+
}

clang-installer/src/downloader/static_dist.rs

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ pub enum StaticDistDownloadError {
4343
#[error("Failed to parse the SHA512 sum file")]
4444
Sha512Corruption,
4545
}
46-
const MIN_CLANG_TOOLS_VERSION: u8 = 11;
47-
pub(crate) const MAX_CLANG_TOOLS_VERSION: u8 = 22;
46+
const MIN_CLANG_TOOLS_VERSION: &str = env!("MIN_CLANG_TOOLS_VERSION");
47+
pub(crate) const MAX_CLANG_TOOLS_VERSION: &str = env!("MAX_CLANG_TOOLS_VERSION");
4848
const CLANG_TOOLS_REPO: &str = "https://github.com/cpp-linter/clang-tools-static-binaries";
49-
const CLANG_TOOLS_TAG: &str = "master-6e612956";
49+
const CLANG_TOOLS_TAG: &str = env!("CLANG_TOOLS_TAG");
5050

5151
/// A downloader that uses statically linked binary distribution files
5252
/// provided by the cpp-linter team.
@@ -56,25 +56,8 @@ impl Cacher for StaticDistDownloader {}
5656

5757
impl StaticDistDownloader {
5858
pub fn get_major_version_range() -> RangeInclusive<u8> {
59-
let min_clang_tools_version: u8 = option_env!("MIN_CLANG_TOOLS_VERSION")
60-
.and_then(|v| match v.parse::<u8>() {
61-
Ok(parsed) => Some(parsed),
62-
Err(e) => {
63-
log::error!("Invalid MIN_CLANG_TOOLS_VERSION env var value: {v}. Error: {e}");
64-
None
65-
}
66-
})
67-
.unwrap_or(MIN_CLANG_TOOLS_VERSION);
68-
let max_clang_tools_version: u8 = option_env!("MAX_CLANG_TOOLS_VERSION")
69-
.and_then(|v| match v.parse::<u8>() {
70-
Ok(parsed) => Some(parsed),
71-
Err(e) => {
72-
log::error!("Invalid MAX_CLANG_TOOLS_VERSION env var value: {v}. Error: {e}");
73-
None
74-
}
75-
})
76-
.unwrap_or(MAX_CLANG_TOOLS_VERSION);
77-
min_clang_tools_version..=max_clang_tools_version
59+
MIN_CLANG_TOOLS_VERSION.parse().unwrap_or(11)
60+
..=MAX_CLANG_TOOLS_VERSION.parse().unwrap_or(22)
7861
}
7962

8063
/// Finds a suitable version from `req_ver` within the range of available clang tools versions.
@@ -83,6 +66,7 @@ impl StaticDistDownloader {
8366
/// `MAX_CLANG_TOOLS_VERSION` environment variables (inclusive) at compile time.
8467
fn find_suitable_version(req_ver: &VersionReq) -> Option<Version> {
8568
let clang_tools_versions: RangeInclusive<u8> = Self::get_major_version_range();
69+
println!("Available clang tools versions: {clang_tools_versions:?}");
8670
let outlier = Version::new(12, 0, 1);
8771
for ver in clang_tools_versions
8872
.map(|v| Version::new(v as u64, 0, 0))

0 commit comments

Comments
 (0)