Add support for "download"
This commit is contained in:
parent
588db24344
commit
eee04a48d9
@ -1,9 +1,9 @@
|
||||
use crate::utils::{get_os_name, rustc_version_info, split_args};
|
||||
use crate::utils::{get_os_name, run_command_with_output, rustc_version_info, split_args};
|
||||
use std::collections::HashMap;
|
||||
use std::env as std_env;
|
||||
use std::ffi::OsStr;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use boml::{types::TomlValue, Toml};
|
||||
|
||||
@ -23,8 +23,12 @@ impl Channel {
|
||||
}
|
||||
}
|
||||
|
||||
fn failed_config_parsing(config_file: &str, err: &str) -> Result<ConfigFile, String> {
|
||||
Err(format!("Failed to parse `{}`: {}", config_file, err))
|
||||
fn failed_config_parsing(config_file: &Path, err: &str) -> Result<ConfigFile, String> {
|
||||
Err(format!(
|
||||
"Failed to parse `{}`: {}",
|
||||
config_file.display(),
|
||||
err
|
||||
))
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
@ -34,12 +38,11 @@ pub struct ConfigFile {
|
||||
}
|
||||
|
||||
impl ConfigFile {
|
||||
pub fn new(config_file: Option<&str>) -> Result<Self, String> {
|
||||
let config_file = config_file.unwrap_or("config.toml");
|
||||
pub fn new(config_file: &Path) -> Result<Self, String> {
|
||||
let content = fs::read_to_string(config_file).map_err(|_| {
|
||||
format!(
|
||||
"Failed to read `{}`. Take a look at `Readme.md` to see how to set up the project",
|
||||
config_file,
|
||||
config_file.display(),
|
||||
)
|
||||
})?;
|
||||
let toml = Toml::parse(&content).map_err(|err| {
|
||||
@ -70,19 +73,30 @@ impl ConfigFile {
|
||||
_ => return failed_config_parsing(config_file, &format!("Unknown key `{}`", key)),
|
||||
}
|
||||
}
|
||||
if config.gcc_path.is_none() && config.download_gccjit.is_none() {
|
||||
return failed_config_parsing(
|
||||
config_file,
|
||||
"At least one of `gcc-path` or `download-gccjit` value must be set",
|
||||
);
|
||||
}
|
||||
if let Some(gcc_path) = config.gcc_path.as_mut() {
|
||||
let path = Path::new(gcc_path);
|
||||
*gcc_path = path
|
||||
.canonicalize()
|
||||
.map_err(|err| format!("Failed to get absolute path of `{}`: {:?}", gcc_path, err))?
|
||||
.display()
|
||||
.to_string();
|
||||
match (config.gcc_path.as_mut(), config.download_gccjit) {
|
||||
(None, None | Some(false)) => {
|
||||
return failed_config_parsing(
|
||||
config_file,
|
||||
"At least one of `gcc-path` or `download-gccjit` value must be set",
|
||||
)
|
||||
}
|
||||
(Some(_), Some(true)) => {
|
||||
println!(
|
||||
"WARNING: both `gcc-path` and `download-gccjit` arguments are used, \
|
||||
ignoring `gcc-path`"
|
||||
);
|
||||
}
|
||||
(Some(gcc_path), _) => {
|
||||
let path = Path::new(gcc_path);
|
||||
*gcc_path = path
|
||||
.canonicalize()
|
||||
.map_err(|err| {
|
||||
format!("Failed to get absolute path of `{}`: {:?}", gcc_path, err)
|
||||
})?
|
||||
.display()
|
||||
.to_string();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Ok(config)
|
||||
}
|
||||
@ -104,6 +118,7 @@ pub struct ConfigInfo {
|
||||
pub sysroot_path: String,
|
||||
pub gcc_path: String,
|
||||
config_file: Option<String>,
|
||||
cg_gcc_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl ConfigInfo {
|
||||
@ -146,6 +161,14 @@ impl ConfigInfo {
|
||||
"--release-sysroot" => self.sysroot_release_channel = true,
|
||||
"--release" => self.channel = Channel::Release,
|
||||
"--sysroot-panic-abort" => self.sysroot_panic_abort = true,
|
||||
"--cg_gcc-path" => match args.next() {
|
||||
Some(arg) if !arg.is_empty() => {
|
||||
self.cg_gcc_path = Some(arg.into());
|
||||
}
|
||||
_ => {
|
||||
return Err("Expected a value after `--cg_gcc-path`, found nothing".to_string())
|
||||
}
|
||||
},
|
||||
_ => return Ok(false),
|
||||
}
|
||||
Ok(true)
|
||||
@ -159,16 +182,144 @@ impl ConfigInfo {
|
||||
command
|
||||
}
|
||||
|
||||
pub fn setup_gcc_path(&mut self) -> Result<(), String> {
|
||||
let ConfigFile { gcc_path, .. } = ConfigFile::new(self.config_file.as_deref())?;
|
||||
fn download_gccjit_if_needed(&mut self) -> Result<(), String> {
|
||||
let output_dir = Path::new(
|
||||
std::env::var("CARGO_TARGET_DIR")
|
||||
.as_deref()
|
||||
.unwrap_or("target"),
|
||||
)
|
||||
.join("libgccjit");
|
||||
|
||||
let commit_hash_file = self.compute_path("libgccjit.version");
|
||||
let content = fs::read_to_string(&commit_hash_file).map_err(|_| {
|
||||
format!(
|
||||
"Failed to read `{}`. Take a look at `Readme.md` to see how to set up the project",
|
||||
commit_hash_file.display(),
|
||||
)
|
||||
})?;
|
||||
let commit = content.trim();
|
||||
if commit.contains('/') || commit.contains('\\') {
|
||||
return Err(format!(
|
||||
"{}: invalid commit hash `{}`",
|
||||
commit_hash_file.display(),
|
||||
commit
|
||||
));
|
||||
}
|
||||
let output_dir = output_dir.join(commit);
|
||||
if !output_dir.is_dir() {
|
||||
std::fs::create_dir_all(&output_dir).map_err(|err| {
|
||||
format!(
|
||||
"failed to create folder `{}`: {:?}",
|
||||
output_dir.display(),
|
||||
err,
|
||||
)
|
||||
})?;
|
||||
}
|
||||
let libgccjit_so = output_dir.join("libgccjit.so");
|
||||
if !libgccjit_so.is_file() {
|
||||
// Download time!
|
||||
let tempfile_name = "libgccjit.so.download";
|
||||
let tempfile = output_dir.join(tempfile_name);
|
||||
let is_in_ci = std::env::var("GITHUB_ACTIONS").is_ok();
|
||||
|
||||
let url = format!(
|
||||
"https://github.com/antoyo/gcc/releases/download/master-{}/libgccjit.so",
|
||||
commit,
|
||||
);
|
||||
|
||||
println!("Downloading `{}`...", url);
|
||||
// Try curl. If that fails and we are on windows, fallback to PowerShell.
|
||||
let mut ret = run_command_with_output(
|
||||
&[
|
||||
&"curl",
|
||||
&"--speed-time",
|
||||
&"30",
|
||||
&"--speed-limit",
|
||||
&"10", // timeout if speed is < 10 bytes/sec for > 30 seconds
|
||||
&"--connect-timeout",
|
||||
&"30", // timeout if cannot connect within 30 seconds
|
||||
&"-o",
|
||||
&tempfile_name,
|
||||
&"--retry",
|
||||
&"3",
|
||||
&"-SRfL",
|
||||
if is_in_ci { &"-s" } else { &"--progress-bar" },
|
||||
&url.as_str(),
|
||||
],
|
||||
Some(&output_dir),
|
||||
);
|
||||
if ret.is_err() && cfg!(windows) {
|
||||
eprintln!("Fallback to PowerShell");
|
||||
ret = run_command_with_output(
|
||||
&[
|
||||
&"PowerShell.exe",
|
||||
&"/nologo",
|
||||
&"-Command",
|
||||
&"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;",
|
||||
&format!(
|
||||
"(New-Object System.Net.WebClient).DownloadFile('{}', '{}')",
|
||||
url,
|
||||
tempfile_name,
|
||||
).as_str(),
|
||||
],
|
||||
Some(&output_dir),
|
||||
);
|
||||
}
|
||||
ret?;
|
||||
|
||||
// If we reach this point, it means the file was correctly downloaded, so let's
|
||||
// rename it!
|
||||
std::fs::rename(&tempfile, &libgccjit_so).map_err(|err| {
|
||||
format!(
|
||||
"Failed to rename `{}` into `{}`: {:?}",
|
||||
tempfile.display(),
|
||||
libgccjit_so.display(),
|
||||
err,
|
||||
)
|
||||
})?;
|
||||
|
||||
println!("Downloaded libgccjit.so version {} successfully!", commit);
|
||||
}
|
||||
|
||||
self.gcc_path = output_dir
|
||||
.canonicalize()
|
||||
.map_err(|err| {
|
||||
format!(
|
||||
"Failed to get absolute path of `{}`: {:?}",
|
||||
output_dir.display(),
|
||||
err
|
||||
)
|
||||
})?
|
||||
.display()
|
||||
.to_string();
|
||||
println!("Using `{}` as path for libgccjit", self.gcc_path);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn compute_path<P: AsRef<Path>>(&self, other: P) -> PathBuf {
|
||||
match self.cg_gcc_path {
|
||||
Some(ref path) => path.join(other),
|
||||
None => PathBuf::new().join(other),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setup_gcc_path(&mut self) -> Result<(), String> {
|
||||
let config_file = self.compute_path(self.config_file.as_deref().unwrap_or("config.toml"));
|
||||
let ConfigFile {
|
||||
gcc_path,
|
||||
download_gccjit,
|
||||
} = ConfigFile::new(&config_file)?;
|
||||
|
||||
if let Some(true) = download_gccjit {
|
||||
self.download_gccjit_if_needed()?;
|
||||
return Ok(());
|
||||
}
|
||||
self.gcc_path = match gcc_path {
|
||||
Some(path) => path,
|
||||
// FIXME: Once we support "download", rewrite this.
|
||||
None => {
|
||||
return Err(format!(
|
||||
"missing `gcc-path` value from `{}`",
|
||||
self.config_file.as_deref().unwrap_or("config.toml"),
|
||||
config_file.display(),
|
||||
))
|
||||
}
|
||||
};
|
||||
@ -362,7 +513,9 @@ impl ConfigInfo {
|
||||
--release : Build in release mode
|
||||
--release-sysroot : Build sysroot in release mode
|
||||
--sysroot-panic-abort : Build the sysroot without unwinding support
|
||||
--config-file : Location of the config file to be used"
|
||||
--config-file : Location of the config file to be used
|
||||
--cg_gcc-path : Location of the rustc_codegen_gcc root folder (used
|
||||
for accessing any file from the project)"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
1
libgccjit.version
Normal file
1
libgccjit.version
Normal file
@ -0,0 +1 @@
|
||||
2fc8940e1
|
Loading…
x
Reference in New Issue
Block a user