mirror of
https://github.com/Jake-Shadle/xwin
synced 2026-06-08 11:22:36 +00:00
+1
-1
@@ -46,7 +46,6 @@ rustflags = [
|
||||
"-Wclippy::match_wild_err_arm",
|
||||
"-Wclippy::match_wildcard_for_single_variants",
|
||||
"-Wclippy::mem_forget",
|
||||
"-Wclippy::mismatched_target_os",
|
||||
"-Wclippy::missing_enforced_import_renames",
|
||||
"-Wclippy::mut_mut",
|
||||
"-Wclippy::mutex_integer",
|
||||
@@ -79,5 +78,6 @@ rustflags = [
|
||||
"-Wfuture_incompatible",
|
||||
"-Wnonstandard_style",
|
||||
"-Wrust_2018_idioms",
|
||||
"-Wunexpected_cfgs",
|
||||
# END - Embark standard lints v5 for Rust 1.55+
|
||||
]
|
||||
|
||||
Generated
+359
-459
File diff suppressed because it is too large
Load Diff
+9
-10
@@ -3,7 +3,7 @@ name = "xwin"
|
||||
version = "0.6.6-rc.2"
|
||||
description = "Allows downloading and repacking the MSVC CRT and Windows SDK for cross compilation"
|
||||
authors = ["Jake Shadle <jake.shadle@embark-studios.com>"]
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
license = "Apache-2.0 OR MIT"
|
||||
repository = "https://github.com/Jake-Shadle/xwin"
|
||||
homepage = "https://github.com/Jake-Shadle/xwin"
|
||||
@@ -31,13 +31,13 @@ native-tls = ["ureq/native-tls", "native-tls-crate/vendored"]
|
||||
# Easy errors
|
||||
anyhow = "1.0"
|
||||
# Network/file buffers
|
||||
bytes = "1.7"
|
||||
bytes = "1.10"
|
||||
# CAB files are used in conjunction with MSI files for SDK packages
|
||||
cab = "0.6"
|
||||
# Nicer to use utf-8 paths
|
||||
camino = "1.0"
|
||||
# Easy CLI tables
|
||||
cli-table = { version = "0.4", default-features = false }
|
||||
cli-table = { version = "0.5", default-features = false }
|
||||
crossbeam-channel = "0.5"
|
||||
# Pretty progress bars
|
||||
indicatif = "0.17"
|
||||
@@ -49,7 +49,7 @@ rayon = "1.5"
|
||||
# Include scanning
|
||||
regex = "1.11"
|
||||
# HTTP requests
|
||||
ureq = { version = "3.0.0-rc1", default-features = false, features = ["gzip", "socks-proxy"] }
|
||||
ureq = { version = "3.0.0", default-features = false, features = ["gzip", "socks-proxy"] }
|
||||
memchr = "2.6"
|
||||
native-tls-crate = { package = "native-tls", version = "0.2", optional = true }
|
||||
# SHA-256 verification
|
||||
@@ -61,8 +61,7 @@ serde_json = "1.0"
|
||||
# Argument parsing
|
||||
clap = { version = "4.5", features = ["derive", "env", "wrap_help"] }
|
||||
# Easy management of temp files
|
||||
tempfile = "3.13"
|
||||
# We need to pin it to not get duplicates due to zip -> num_enum -> proc-macro-crate -> (WHY!?!?) toml_edit
|
||||
tempfile = "3.19"
|
||||
toml = "0.8"
|
||||
# Tracing logs
|
||||
tracing = { version = "0.1", default-features = false, features = [
|
||||
@@ -76,19 +75,19 @@ tracing-subscriber = { version = "0.3", default-features = false, features = [
|
||||
"json",
|
||||
] }
|
||||
# Hashing
|
||||
twox-hash = "1.6"
|
||||
twox-hash = "2.1"
|
||||
# Determine the latest CRT and SDK versions
|
||||
versions = "6.2"
|
||||
versions = "7.0"
|
||||
walkdir = "2.3"
|
||||
# Unpacking of VSIX "packages"
|
||||
zip = { version = "2.1", default-features = false, features = ["deflate"] }
|
||||
zip = { version = "2.6", default-features = false, features = ["deflate"] }
|
||||
|
||||
[target.'cfg(all(target_env = "musl", target_arch = "x86_64"))'.dependencies]
|
||||
# Faster allocator for musl builds
|
||||
mimalloc = { version = "0.1", default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
insta = "1.40"
|
||||
insta = "1.42"
|
||||
|
||||
[profile.dev.package.insta]
|
||||
opt-level = 3
|
||||
|
||||
@@ -16,28 +16,17 @@ exceptions = [
|
||||
# ring uses code from multiple libraries but all with permissive licenses
|
||||
# https://tldrlegal.com/license/openssl-license-(openssl)
|
||||
{ allow = ["ISC", "MIT", "OpenSSL"], name = "ring" },
|
||||
{ allow = ["Unicode-DFS-2016"], name = "unicode-ident" },
|
||||
{ allow = ["Unicode-3.0"], name = "unicode-ident" },
|
||||
{ allow = ["BSL-1.0"], name = "lockfree-object-pool" },
|
||||
]
|
||||
|
||||
[[licenses.clarify]]
|
||||
name = "ring"
|
||||
# SPDX considers OpenSSL to encompass both the OpenSSL and SSLeay licenses
|
||||
# https://spdx.org/licenses/OpenSSL.html
|
||||
# ISC - Both BoringSSL and ring use this for their new files
|
||||
# MIT - "Files in third_party/ have their own licenses, as described therein. The MIT
|
||||
# license, for third_party/fiat, which, unlike other third_party directories, is
|
||||
# compiled into non-test libraries, is included below."
|
||||
# OpenSSL - Obviously
|
||||
expression = "ISC AND MIT AND OpenSSL"
|
||||
license-files = [{ path = "LICENSE", hash = 0xbd0eed23 }]
|
||||
|
||||
[bans]
|
||||
multiple-versions = "deny"
|
||||
deny = []
|
||||
skip = [
|
||||
{ crate = "regex-syntax@0.6.29", reason = "tracing-subscriber depends on 2 different versions :(" },
|
||||
{ crate = "regex-automata@0.1.10", reason = "tracing-subscriber depends on 2 different versions :(" },
|
||||
{ crate = "getrandom@0.2.15", reason = "rand_core/ring use this old version, lol" },
|
||||
]
|
||||
skip-tree = []
|
||||
|
||||
|
||||
+18
-14
@@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
Path, PathBuf, WorkItem,
|
||||
splat::SdkHeaders,
|
||||
util::{ProgressTarget, Sha256},
|
||||
Path, PathBuf, WorkItem,
|
||||
};
|
||||
use anyhow::{Context as _, Error};
|
||||
|
||||
@@ -87,28 +87,25 @@ impl Ctx {
|
||||
tracing::debug!("verifying existing cached dl file");
|
||||
|
||||
match std::fs::read(&cache_path) {
|
||||
Ok(contents) => match &checksum {
|
||||
Some(expected) => {
|
||||
Ok(contents) => {
|
||||
if let Some(expected) = &checksum {
|
||||
let chksum = Sha256::digest(&contents);
|
||||
|
||||
if chksum != *expected {
|
||||
tracing::warn!(
|
||||
"checksum mismatch, expected {} != actual {}",
|
||||
expected,
|
||||
chksum
|
||||
"checksum mismatch, expected {expected} != actual {chksum}",
|
||||
);
|
||||
} else {
|
||||
progress.inc_length(contents.len() as u64);
|
||||
progress.inc(contents.len() as u64);
|
||||
return Ok(contents.into());
|
||||
}
|
||||
}
|
||||
None => {
|
||||
} else {
|
||||
progress.inc_length(contents.len() as u64);
|
||||
progress.inc(contents.len() as u64);
|
||||
return Ok(contents.into());
|
||||
}
|
||||
},
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::warn!(error = %e, "failed to read cached file");
|
||||
}
|
||||
@@ -165,7 +162,11 @@ impl Ctx {
|
||||
|
||||
if body.capacity() > 0 {
|
||||
if body.capacity() as u64 != content_length {
|
||||
tracing::warn!(url = url.as_ref(), "a previous HTTP GET had a content-length of {}, but we now received a content-length of {content_length}", body.capacity());
|
||||
tracing::warn!(
|
||||
url = url.as_ref(),
|
||||
"a previous HTTP GET had a content-length of {}, but we now received a content-length of {content_length}",
|
||||
body.capacity()
|
||||
);
|
||||
|
||||
if body.capacity() as u64 > content_length {
|
||||
progress.inc_length(body.capacity() as u64 - content_length);
|
||||
@@ -236,8 +237,6 @@ impl Ctx {
|
||||
"HTTP GET failed to retrieve entire body, retrying"
|
||||
);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
Err(DownloadError::Ureq(err)) => {
|
||||
return Err(err)
|
||||
@@ -250,7 +249,10 @@ impl Ctx {
|
||||
}
|
||||
}
|
||||
|
||||
anyhow::bail!("failed to retrieve {} after {total} tries due to I/O failures reading the response body, try using --http-retries to increase the retry count", url.as_ref());
|
||||
anyhow::bail!(
|
||||
"failed to retrieve {} after {total} tries due to I/O failures reading the response body, try using --http-retries to increase the retry count",
|
||||
url.as_ref()
|
||||
);
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
@@ -320,7 +322,9 @@ impl Ctx {
|
||||
})?;
|
||||
|
||||
let enable_symlinks = if std::fs::read(root.join("big.xwin")).is_ok() {
|
||||
tracing::warn!("detected splat root '{root}' is on a case-sensitive file system, disabling symlinks");
|
||||
tracing::warn!(
|
||||
"detected splat root '{root}' is on a case-sensitive file system, disabling symlinks"
|
||||
);
|
||||
false
|
||||
} else {
|
||||
true
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
use crate::{manifest, util::Sha256, Ctx, Error};
|
||||
use crate::{Ctx, Error, manifest, util::Sha256};
|
||||
use anyhow::Context as _;
|
||||
use camino::Utf8PathBuf as PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
+3
-3
@@ -630,9 +630,9 @@ fn get_sdk(
|
||||
.file_name
|
||||
.strip_prefix("Installers\\Windows SDK Desktop Headers ")
|
||||
.and_then(|fname| fname.strip_suffix("-x86_en-us.msi"))
|
||||
.map_or(false, |fname| fname == arch.as_ms_str())
|
||||
.is_some_and(|fname| fname == arch.as_ms_str())
|
||||
})
|
||||
.with_context(|| format!("unable to find {} headers for {}", arch, sdk.id))?;
|
||||
.with_context(|| format!("unable to find {arch} headers for {}", sdk.id))?;
|
||||
|
||||
pruned.push(Payload {
|
||||
filename: format!("{}_{}_headers.msi", sdk.id, arch.as_ms_str()).into(),
|
||||
@@ -660,7 +660,7 @@ fn get_sdk(
|
||||
.file_name
|
||||
.strip_prefix("Installers\\Windows SDK Desktop Libs ")
|
||||
.and_then(|fname| fname.strip_suffix("-x86_en-us.msi"))
|
||||
.map_or(false, |arch_id| arch_id == arch.as_ms_str())
|
||||
.is_some_and(|arch_id| arch_id == arch.as_ms_str())
|
||||
})
|
||||
.with_context(|| format!("unable to find SDK libs for '{}'", arch))?;
|
||||
|
||||
|
||||
+14
-14
@@ -261,7 +261,9 @@ fn main() -> Result<(), Error> {
|
||||
if !args.accept_license {
|
||||
// The license link is the same for every locale, but we should probably
|
||||
// retrieve it from the manifest in the future
|
||||
println!("Do you accept the license at https://go.microsoft.com/fwlink/?LinkId=2086102 (yes | no)?");
|
||||
println!(
|
||||
"Do you accept the license at https://go.microsoft.com/fwlink/?LinkId=2086102 (yes | no)?"
|
||||
);
|
||||
|
||||
let mut accept = String::new();
|
||||
std::io::stdin().read_line(&mut accept)?;
|
||||
@@ -279,15 +281,15 @@ fn main() -> Result<(), Error> {
|
||||
let draw_target = xwin::util::ProgressTarget::Stdout;
|
||||
|
||||
let client = {
|
||||
let mut builder = ureq::Config::new();
|
||||
builder.timeouts.recv_body = Some(args.timeout);
|
||||
let mut builder = ureq::config::Config::builder();
|
||||
builder = builder.timeout_recv_body(Some(args.timeout));
|
||||
|
||||
if let Some(proxy) = args.https_proxy {
|
||||
let proxy = ureq::Proxy::new(&proxy).context("failed to parse https proxy address")?;
|
||||
builder.proxy = Some(proxy);
|
||||
builder = builder.proxy(Some(proxy));
|
||||
}
|
||||
|
||||
ureq::Agent::new_with_config(builder)
|
||||
builder.build().new_agent()
|
||||
};
|
||||
|
||||
let ctx = if args.temp {
|
||||
@@ -448,7 +450,7 @@ fn main() -> Result<(), Error> {
|
||||
}
|
||||
|
||||
fn print_packages(payloads: &[xwin::Payload]) {
|
||||
use cli_table::{format::Justify, Cell, Style, Table};
|
||||
use cli_table::{Cell, Style, Table, format::Justify};
|
||||
|
||||
let (dl, install) = payloads.iter().fold((0, 0), |(dl, install), payload| {
|
||||
(
|
||||
@@ -590,9 +592,11 @@ mod test {
|
||||
// use internal `insta` function instead of the macro so we can pass in the
|
||||
// right module information from the crate and to gather up the errors instead of panicking directly on failures
|
||||
insta::_macro_support::assert_snapshot(
|
||||
cmd_name.clone().into(),
|
||||
help_text,
|
||||
desc.manifest_path,
|
||||
insta::_macro_support::SnapshotValue::FileText {
|
||||
name: Some(cmd_name.as_str().into()),
|
||||
content: help_text,
|
||||
},
|
||||
std::path::Path::new(&desc.manifest_path),
|
||||
"cli-cmd",
|
||||
desc.module_path,
|
||||
desc.file,
|
||||
@@ -607,11 +611,7 @@ mod test {
|
||||
continue;
|
||||
}
|
||||
|
||||
snapshot_test_cli_command(
|
||||
app.clone(),
|
||||
format!("{}-{}", cmd_name, app.get_name()),
|
||||
desc,
|
||||
);
|
||||
snapshot_test_cli_command(app.clone(), format!("{cmd_name}-{}", app.get_name()), desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
use anyhow::{ensure, Context as _};
|
||||
use anyhow::{Context as _, ensure};
|
||||
use serde::Deserialize;
|
||||
use std::{cmp, collections::BTreeMap};
|
||||
|
||||
|
||||
+10
-5
@@ -1,4 +1,4 @@
|
||||
use crate::{util::canonicalize, Ctx, Path, PathBuf, SectionKind};
|
||||
use crate::{Ctx, Path, PathBuf, SectionKind, util::canonicalize};
|
||||
use anyhow::Context as _;
|
||||
|
||||
pub struct MinimizeConfig {
|
||||
@@ -60,7 +60,7 @@ pub(crate) fn minimize(
|
||||
"--manifest-path",
|
||||
config.manifest_path.as_str(),
|
||||
]);
|
||||
if !clean.status().map_or(false, |s| s.success()) {
|
||||
if !clean.status().is_ok_and(|s| s.success()) {
|
||||
tracing::error!("failed to clean cargo target directory");
|
||||
}
|
||||
|
||||
@@ -100,7 +100,9 @@ pub(crate) fn minimize(
|
||||
"-Wno-unused-command-line-argument -fuse-ld=lld-link /vctoolsdir {splat_root}/crt /winsdkdir {splat_root}/sdk"
|
||||
);
|
||||
|
||||
let mut libs = format!("-C linker=lld-link -Lnative={splat_root}/crt/lib/x86_64 -Lnative={splat_root}/sdk/lib/um/x86_64 -Lnative={splat_root}/sdk/lib/ucrt/x86_64");
|
||||
let mut libs = format!(
|
||||
"-C linker=lld-link -Lnative={splat_root}/crt/lib/x86_64 -Lnative={splat_root}/sdk/lib/um/x86_64 -Lnative={splat_root}/sdk/lib/ucrt/x86_64"
|
||||
);
|
||||
|
||||
let rust_flags_env = format!(
|
||||
"CARGO_TARGET_{}_RUSTFLAGS",
|
||||
@@ -144,7 +146,10 @@ pub(crate) fn minimize(
|
||||
Ok(f) => break f,
|
||||
Err(err) => {
|
||||
if start.elapsed() > max {
|
||||
anyhow::bail!("failed to open strace output '{}' after waiting for {max:?}: {err}", strace_output_path.display());
|
||||
anyhow::bail!(
|
||||
"failed to open strace output '{}' after waiting for {max:?}: {err}",
|
||||
strace_output_path.display()
|
||||
);
|
||||
}
|
||||
|
||||
std::thread::sleep(std::time::Duration::from_millis(10));
|
||||
@@ -173,7 +178,7 @@ pub(crate) fn minimize(
|
||||
let available = match output.fill_buf() {
|
||||
Ok(n) => n,
|
||||
Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => {
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
Err(e) => anyhow::bail!(e),
|
||||
};
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
use crate::{symlink, Arch, Ctx, Error, Path, PathBuf, PayloadKind, SectionKind, Variant};
|
||||
use crate::{Arch, Ctx, Error, Path, PathBuf, PayloadKind, SectionKind, Variant, symlink};
|
||||
use anyhow::Context as _;
|
||||
use rayon::prelude::*;
|
||||
use std::collections::BTreeMap;
|
||||
@@ -552,7 +552,7 @@ pub(crate) fn splat(
|
||||
|| stripped.ends_with("d_netcore")
|
||||
|| stripped
|
||||
.strip_suffix(|c: char| c.is_ascii_digit())
|
||||
.map_or(false, |fname| fname.ends_with('d'))
|
||||
.is_some_and(|fname| fname.ends_with('d'))
|
||||
{
|
||||
tracing::debug!("skipping {fname}");
|
||||
continue;
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
use crate::{download::PayloadContents, Ctx, Error, Path, PathBuf};
|
||||
use crate::{Ctx, Error, Path, PathBuf, download::PayloadContents};
|
||||
use anyhow::Context as _;
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
@@ -535,7 +535,7 @@ pub(crate) fn unpack(
|
||||
uf: std::fs::File,
|
||||
}
|
||||
|
||||
impl<'pb> std::io::Write for Wrapper<'pb> {
|
||||
impl std::io::Write for Wrapper<'_> {
|
||||
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
||||
self.pb.inc(buf.len() as u64);
|
||||
self.uf.write(buf)
|
||||
|
||||
+1
-1
@@ -96,7 +96,7 @@ impl<'de> serde::Deserialize<'de> for Sha256 {
|
||||
{
|
||||
struct Visitor;
|
||||
|
||||
impl<'de> serde::de::Visitor<'de> for Visitor {
|
||||
impl serde::de::Visitor<'_> for Visitor {
|
||||
type Value = Sha256;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
||||
+11
-5
@@ -101,7 +101,9 @@ fn verify_compiles() {
|
||||
let includes = match style {
|
||||
Style::Default => {
|
||||
cmd.env("RUSTFLAGS", format!("-C linker=lld-link -Lnative={od}/crt/lib/x86_64 -Lnative={od}/sdk/lib/um/x86_64 -Lnative={od}/sdk/lib/ucrt/x86_64"));
|
||||
format!("-Wno-unused-command-line-argument -fuse-ld=lld-link /imsvc{od}/crt/include /imsvc{od}/sdk/include/ucrt /imsvc{od}/sdk/include/um /imsvc{od}/sdk/include/shared")
|
||||
format!(
|
||||
"-Wno-unused-command-line-argument -fuse-ld=lld-link /imsvc{od}/crt/include /imsvc{od}/sdk/include/ucrt /imsvc{od}/sdk/include/um /imsvc{od}/sdk/include/shared"
|
||||
)
|
||||
}
|
||||
Style::WinSysRoot => {
|
||||
const SEP: char = '\x1F';
|
||||
@@ -142,9 +144,11 @@ fn verify_compiles() {
|
||||
]);
|
||||
|
||||
let includes = format!(
|
||||
"-Wno-unused-command-line-argument -fuse-ld=lld-link /vctoolsdir {od}/crt /winsdkdir {od}/sdk"
|
||||
);
|
||||
let libs = format!("-C linker=lld-link -Lnative={od}/crt/lib/x86_64 -Lnative={od}/sdk/lib/um/x86_64 -Lnative={od}/sdk/lib/ucrt/x86_64");
|
||||
"-Wno-unused-command-line-argument -fuse-ld=lld-link /vctoolsdir {od}/crt /winsdkdir {od}/sdk"
|
||||
);
|
||||
let libs = format!(
|
||||
"-C linker=lld-link -Lnative={od}/crt/lib/x86_64 -Lnative={od}/sdk/lib/um/x86_64 -Lnative={od}/sdk/lib/ucrt/x86_64"
|
||||
);
|
||||
|
||||
let cc_env = [
|
||||
("CC_x86_64_pc_windows_msvc", "clang-cl"),
|
||||
@@ -265,7 +269,9 @@ fn verify_compiles_minimized() {
|
||||
let includes = format!(
|
||||
"-Wno-unused-command-line-argument -fuse-ld=lld-link /vctoolsdir {od}/crt /winsdkdir {od}/sdk"
|
||||
);
|
||||
let libs = format!("-C linker=lld-link -Lnative={od}/crt/lib/x86_64 -Lnative={od}/sdk/lib/um/x86_64 -Lnative={od}/sdk/lib/ucrt/x86_64");
|
||||
let libs = format!(
|
||||
"-C linker=lld-link -Lnative={od}/crt/lib/x86_64 -Lnative={od}/sdk/lib/um/x86_64 -Lnative={od}/sdk/lib/ucrt/x86_64"
|
||||
);
|
||||
|
||||
let cc_env = [
|
||||
("CC_x86_64_pc_windows_msvc", "clang-cl"),
|
||||
|
||||
Reference in New Issue
Block a user