Skip to content

Commit 363f486

Browse files
committed
fix: refactor for unsupported static binary platforms
previous builds for unsupported platforms issued a bunch of warnings because of unused code. This refactors the clang-tools-manager/src/downloader/static_dist.rs module to only compile code that is actually used per the compile target.
1 parent 41fcd9e commit 363f486

3 files changed

Lines changed: 197 additions & 128 deletions

File tree

clang-tools-manager/src/downloader/hashing.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,20 @@ use std::{fs, io::Read, num::NonZero, path::Path};
1616
pub enum HashAlgorithm {
1717
/// SHA-256 hash algorithm with the expected checksum value.
1818
Sha256(String),
19+
1920
/// BLAKE2b-256 hash algorithm with the expected checksum value.
2021
Blake2b256(String),
22+
2123
/// SHA-512 hash algorithm with the expected checksum value.
24+
#[cfg(any(
25+
// Windows support is only for x86_64 architecture (for now)
26+
all(target_os = "windows", target_arch = "x86_64"),
27+
// Linux and macOS support only x86_64 and aarch64 architectures
28+
all(
29+
any(target_os = "linux", target_os = "macos"),
30+
any(target_arch = "x86_64", target_arch = "aarch64")
31+
),
32+
))]
2233
Sha512(String),
2334
}
2435

@@ -74,6 +85,15 @@ impl HashAlgorithm {
7485
let hasher = Blake2b::<U32>::new();
7586
Self::hash_file(hasher, file_path, expected)
7687
}
88+
#[cfg(any(
89+
// Windows support is only for x86_64 architecture (for now)
90+
all(target_os = "windows", target_arch = "x86_64"),
91+
// Linux and macOS support only x86_64 and aarch64 architectures
92+
all(
93+
any(target_os = "linux", target_os = "macos"),
94+
any(target_arch = "x86_64", target_arch = "aarch64")
95+
),
96+
))]
7797
HashAlgorithm::Sha512(expected) => {
7898
use sha2::{Digest, Sha512};
7999

clang-tools-manager/src/downloader/static_dist.rs

Lines changed: 168 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,10 @@
22
33
use std::{
44
env::consts::{ARCH, OS},
5-
fs,
65
ops::RangeInclusive,
7-
path::{Path, PathBuf},
86
};
97

10-
use semver::{Version, VersionReq};
11-
use url::Url;
12-
13-
use crate::{
14-
Cacher, ClangTool, DownloadError,
15-
downloader::{download, hashing::HashAlgorithm},
16-
utils::lock_path,
17-
};
8+
use crate::{Cacher, DownloadError};
189

1910
/// An error that can occur while downloading a static binary.
2011
#[derive(Debug, thiserror::Error)]
@@ -45,10 +36,9 @@ pub enum StaticDistDownloadError {
4536
#[error("Failed to parse the SHA512 sum file")]
4637
Sha512Corruption,
4738
}
39+
4840
const MIN_CLANG_TOOLS_VERSION: &str = env!("MIN_CLANG_TOOLS_VERSION");
4941
pub(crate) const MAX_CLANG_TOOLS_VERSION: &str = env!("MAX_CLANG_TOOLS_VERSION");
50-
const CLANG_TOOLS_REPO: &str = "https://github.com/cpp-linter/clang-tools-static-binaries";
51-
const CLANG_TOOLS_TAG: &str = env!("CLANG_TOOLS_TAG");
5242

5343
/// A downloader that uses statically linked binary distribution files
5444
/// provided by the cpp-linter team.
@@ -61,131 +51,181 @@ impl StaticDistDownloader {
6151
MIN_CLANG_TOOLS_VERSION.parse().unwrap_or(11)
6252
..=MAX_CLANG_TOOLS_VERSION.parse().unwrap_or(22)
6353
}
54+
}
6455

65-
/// Finds a suitable version from `req_ver` within the range of available clang tools versions.
66-
///
67-
/// The available versions are determined by the `MIN_CLANG_TOOLS_VERSION` and
68-
/// `MAX_CLANG_TOOLS_VERSION` environment variables (inclusive) at compile time.
69-
fn find_suitable_version(req_ver: &VersionReq) -> Option<Version> {
70-
let clang_tools_versions: RangeInclusive<u8> = Self::get_major_version_range();
71-
clang_tools_versions
72-
.map(|v| Version::new(v as u64, 0, 0))
73-
.rev()
74-
.find(|ver| req_ver.matches(ver))
56+
#[cfg(any(
57+
// Windows support is only for x86_64 architecture (for now)
58+
all(target_os = "windows", not(target_arch = "x86_64")),
59+
// Linux and macOS support only x86_64 and aarch64 architectures
60+
all(
61+
any(target_os = "linux", target_os = "macos"),
62+
not(any(target_arch = "x86_64", target_arch = "aarch64"))
63+
),
64+
// Any OS other than Windows, Linux, or macOS is unsupported
65+
not(any(target_os = "windows", target_os = "linux", target_os = "macos")),
66+
))]
67+
mod unsupported_platform {
68+
use super::{StaticDistDownloadError, StaticDistDownloader};
69+
use crate::ClangTool;
70+
use semver::VersionReq;
71+
use std::path::PathBuf;
72+
73+
impl StaticDistDownloader {
74+
pub async fn download_tool(
75+
_tool: &ClangTool,
76+
_requested_version: &VersionReq,
77+
_directory: Option<&PathBuf>,
78+
) -> Result<PathBuf, StaticDistDownloadError> {
79+
Err(StaticDistDownloadError::UnsupportedArchitecture)
80+
}
7581
}
82+
}
7683

77-
/// Verifies the SHA512 checksum of the downloaded file.
78-
///
79-
/// The expected checksum is extracted from another downloaded `*.sha512sum` file
80-
/// (pointed to by `sha512_path`).
81-
fn verify_sha512(file_path: &Path, sha512_path: &Path) -> Result<(), StaticDistDownloadError> {
82-
let checksum_file_content = fs::read_to_string(sha512_path)?;
83-
let expected = checksum_file_content
84-
.split(' ')
85-
.next()
86-
.ok_or(StaticDistDownloadError::Sha512Corruption)?;
87-
HashAlgorithm::Sha512(expected.to_string()).verify(file_path)?;
88-
Ok(())
89-
}
84+
#[cfg(any(
85+
// Windows support is only for x86_64 architecture (for now)
86+
all(target_os = "windows", target_arch = "x86_64"),
87+
// Linux and macOS support only x86_64 and aarch64 architectures
88+
all(
89+
any(target_os = "linux", target_os = "macos"),
90+
any(target_arch = "x86_64", target_arch = "aarch64")
91+
),
92+
))]
93+
mod supported_platform {
94+
use std::{
95+
fs,
96+
ops::RangeInclusive,
97+
path::{Path, PathBuf},
98+
};
99+
100+
use semver::{Version, VersionReq};
101+
use url::Url;
102+
103+
use super::{StaticDistDownloadError, StaticDistDownloader};
104+
use crate::{
105+
Cacher, ClangTool,
106+
downloader::{download, hashing::HashAlgorithm},
107+
utils::lock_path,
108+
};
109+
110+
const CLANG_TOOLS_REPO: &str = "https://github.com/cpp-linter/clang-tools-static-binaries";
111+
const CLANG_TOOLS_TAG: &str = env!("CLANG_TOOLS_TAG");
112+
113+
impl StaticDistDownloader {
114+
/// Finds a suitable version from `req_ver` within the range of available clang tools versions.
115+
///
116+
/// The available versions are determined by the `MIN_CLANG_TOOLS_VERSION` and
117+
/// `MAX_CLANG_TOOLS_VERSION` environment variables (inclusive) at compile time.
118+
fn find_suitable_version(req_ver: &VersionReq) -> Option<Version> {
119+
let clang_tools_versions: RangeInclusive<u8> = Self::get_major_version_range();
120+
clang_tools_versions
121+
.map(|v| Version::new(v as u64, 0, 0))
122+
.rev()
123+
.find(|ver| req_ver.matches(ver))
124+
}
90125

91-
/// Downloads the `requested_version` of the specified `tool` from a distribution of statically linked binaries.
92-
///
93-
/// The distribution is maintained at <https://github.com/cpp-linter/clang-tools-static-binaries>.
94-
/// Supported platforms includes Windows, Linux, and MacOS.
95-
/// Supported architectures is limited to `x86_64` (`amd64`).
96-
pub async fn download_tool(
97-
tool: &ClangTool,
98-
requested_version: &VersionReq,
99-
directory: Option<&PathBuf>,
100-
) -> Result<PathBuf, StaticDistDownloadError> {
101-
#[cfg(any(
102-
// Windows support is only for x86_64 architecture (for now)
103-
all(target_os = "windows", not(target_arch = "x86_64")),
104-
// Linux and macOS support only x86_64 and aarch64 architectures
105-
all(
106-
any(target_os = "linux", target_os = "macos"),
107-
not(any(target_arch = "x86_64", target_arch = "aarch64"))
108-
),
109-
// Any OS other than Windows, Linux, or macOS is unsupported
110-
not(any(target_os = "windows", target_os = "linux", target_os = "macos")),
111-
))]
112-
return Err(StaticDistDownloadError::UnsupportedArchitecture);
113-
114-
let ver = Self::find_suitable_version(requested_version)
115-
.ok_or(StaticDistDownloadError::UnsupportedVersion)?;
116-
let ver_str = ver.major.to_string();
117-
// we already gated unsupported architectures above,
118-
// so we can assume it's either x86_64 or aarch64 here
119-
let arch = if cfg!(target_arch = "aarch64") {
120-
"arm64"
121-
} else {
122-
"amd64"
123-
};
124-
let platform = if cfg!(target_os = "windows") {
125-
"windows"
126-
} else if cfg!(target_os = "macos") {
127-
"macos"
128-
} else {
129-
"linux"
130-
};
131-
132-
let base_url = format!(
133-
"{CLANG_TOOLS_REPO}/releases/download/{CLANG_TOOLS_TAG}/{tool}-{ver_str}_{platform}-{arch}",
134-
);
135-
let suffix = if cfg!(target_os = "windows") {
136-
".exe"
137-
} else {
138-
""
139-
};
140-
let url = Url::parse(format!("{base_url}{suffix}").as_str())?;
141-
let cache_path = Self::get_cache_dir();
142-
let bin_name = format!("{tool}-{ver_str}{suffix}");
143-
let download_path = match directory {
144-
None => cache_path.join("bin").join(&bin_name),
145-
Some(dir) => dir.join(&bin_name),
146-
};
147-
let file_lock = lock_path(&download_path)?;
148-
if download_path.exists() {
149-
log::info!(
150-
"Using cached static binary for {tool} version {ver_str} from {:?}",
151-
download_path.to_string_lossy()
152-
);
153-
} else {
154-
log::info!("Downloading static binary for {tool} version {ver_str} from {url}");
155-
download(&url, &download_path, 60 * 2).await?;
156-
#[cfg(unix)]
157-
super::chmod_file(&download_path, None)?;
126+
/// Verifies the SHA512 checksum of the downloaded file.
127+
///
128+
/// The expected checksum is extracted from another downloaded `*.sha512sum` file
129+
/// (pointed to by `sha512_path`).
130+
fn verify_sha512(
131+
file_path: &Path,
132+
sha512_path: &Path,
133+
) -> Result<(), StaticDistDownloadError> {
134+
let checksum_file_content = fs::read_to_string(sha512_path)?;
135+
let expected = checksum_file_content
136+
.split(' ')
137+
.next()
138+
.ok_or(StaticDistDownloadError::Sha512Corruption)?;
139+
HashAlgorithm::Sha512(expected.to_string()).verify(file_path)?;
140+
Ok(())
158141
}
159-
let sha512_cache_path = cache_path
160-
.join("static_dist")
161-
.join(format!("{tool}-{ver_str}.sha512"));
162-
if sha512_cache_path.exists() {
163-
log::info!(
164-
"Using cached SHA512 checksum for {tool} version {ver_str} from {:?}",
165-
sha512_cache_path.to_string_lossy()
166-
);
167-
} else {
168-
let sha512_url = Url::parse(format!("{base_url}{suffix}.sha512sum").as_str())?;
169-
log::info!(
170-
"Downloading SHA512 checksum for {tool} version {ver_str} from {sha512_url}"
142+
143+
/// Downloads the `requested_version` of the specified `tool` from a distribution of statically linked binaries.
144+
///
145+
/// The distribution is maintained at <https://github.com/cpp-linter/clang-tools-static-binaries>.
146+
/// Supported platforms includes Windows, Linux, and MacOS.
147+
/// Supported architectures is limited to `x86_64` (`amd64`).
148+
pub async fn download_tool(
149+
tool: &ClangTool,
150+
requested_version: &VersionReq,
151+
directory: Option<&PathBuf>,
152+
) -> Result<PathBuf, StaticDistDownloadError> {
153+
let ver = Self::find_suitable_version(requested_version)
154+
.ok_or(StaticDistDownloadError::UnsupportedVersion)?;
155+
let ver_str = ver.major.to_string();
156+
// we already gated unsupported architectures above,
157+
// so we can assume it's either x86_64 or aarch64 here
158+
let arch = if cfg!(target_arch = "aarch64") {
159+
"arm64"
160+
} else {
161+
"amd64"
162+
};
163+
let platform = if cfg!(target_os = "windows") {
164+
"windows"
165+
} else if cfg!(target_os = "macos") {
166+
"macos"
167+
} else {
168+
"linux"
169+
};
170+
171+
let base_url = format!(
172+
"{CLANG_TOOLS_REPO}/releases/download/{CLANG_TOOLS_TAG}/{tool}-{ver_str}_{platform}-{arch}",
171173
);
172-
download(&sha512_url, &sha512_cache_path, 10).await?;
174+
let suffix = if cfg!(target_os = "windows") {
175+
".exe"
176+
} else {
177+
""
178+
};
179+
let url = Url::parse(format!("{base_url}{suffix}").as_str())?;
180+
let cache_path = Self::get_cache_dir();
181+
let bin_name = format!("{tool}-{ver_str}{suffix}");
182+
let download_path = match directory {
183+
None => cache_path.join("bin").join(&bin_name),
184+
Some(dir) => dir.join(&bin_name),
185+
};
186+
let file_lock = lock_path(&download_path)?;
187+
if download_path.exists() {
188+
log::info!(
189+
"Using cached static binary for {tool} version {ver_str} from {:?}",
190+
download_path.to_string_lossy()
191+
);
192+
} else {
193+
log::info!("Downloading static binary for {tool} version {ver_str} from {url}");
194+
download(&url, &download_path, 60 * 2).await?;
195+
#[cfg(unix)]
196+
super::super::chmod_file(&download_path, None)?;
197+
}
198+
let sha512_cache_path = cache_path
199+
.join("static_dist")
200+
.join(format!("{tool}-{ver_str}.sha512"));
201+
if sha512_cache_path.exists() {
202+
log::info!(
203+
"Using cached SHA512 checksum for {tool} version {ver_str} from {:?}",
204+
sha512_cache_path.to_string_lossy()
205+
);
206+
} else {
207+
let sha512_url = Url::parse(format!("{base_url}{suffix}.sha512sum").as_str())?;
208+
log::info!(
209+
"Downloading SHA512 checksum for {tool} version {ver_str} from {sha512_url}"
210+
);
211+
download(&sha512_url, &sha512_cache_path, 10).await?;
212+
}
213+
Self::verify_sha512(&download_path, &sha512_cache_path)?;
214+
file_lock.unlock()?;
215+
Ok(download_path)
173216
}
174-
Self::verify_sha512(&download_path, &sha512_cache_path)?;
175-
file_lock.unlock()?;
176-
Ok(download_path)
177217
}
178-
}
179218

180-
#[cfg(test)]
181-
mod tests {
182-
use super::StaticDistDownloader;
183-
use semver::VersionReq;
219+
#[cfg(test)]
220+
mod tests {
221+
use super::StaticDistDownloader;
222+
use semver::VersionReq;
184223

185-
#[test]
186-
fn find_none() {
187-
let req_ver = VersionReq::parse("=8").unwrap();
188-
let suitable_version = StaticDistDownloader::find_suitable_version(&req_ver);
189-
assert_eq!(suitable_version, None);
224+
#[test]
225+
fn find_none() {
226+
let req_ver = VersionReq::parse("=8").unwrap();
227+
let suitable_version = StaticDistDownloader::find_suitable_version(&req_ver);
228+
assert_eq!(suitable_version, None);
229+
}
190230
}
191231
}

nurfile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ def "nur docs rs" [
2020
run-cmd ...$cmd
2121
}
2222

23+
const URL = "https://github.com/cpp-linter/clang-tools-static-binaries/releases/latest/download/versions.json"
24+
25+
# Seed the versions.json file with the latest release from GitHub.
26+
#
27+
# Useful to avoid network requests in local dev builds of clang-tools-manager crate.
28+
# This will instigate a warning, but that is expected.
29+
def "nur seed versions" [] {
30+
let versions = (http get $URL) | save --force clang-tools-manager/versions.json
31+
}
2332

2433
# Build mkdocs output.
2534
#

0 commit comments

Comments
 (0)