Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add clone-gcc command #456

Merged
merged 2 commits into from Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
79 changes: 79 additions & 0 deletions build_system/src/clone_gcc.rs
@@ -0,0 +1,79 @@
use crate::config::ConfigInfo;
use crate::utils::{git_clone, run_command_with_output};

use std::path::{Path, PathBuf};

fn show_usage() {
println!(
r#"
`clone-gcc` command help:

--out-path : Location where the GCC repository will be cloned (default: `./gcc`)"#
);
ConfigInfo::show_usage();
println!(" --help : Show this help");
}

#[derive(Default)]
struct Args {
out_path: PathBuf,
config_info: ConfigInfo,
}

impl Args {
fn new() -> Result<Option<Self>, String> {
let mut command_args = Self::default();

let mut out_path = None;

// We skip binary name and the `clone-gcc` command.
let mut args = std::env::args().skip(2);

while let Some(arg) = args.next() {
match arg.as_str() {
"--out-path" => match args.next() {
Some(path) if !path.is_empty() => out_path = Some(path),
_ => {
return Err("Expected an argument after `--out-path`, found nothing".into())
}
},
"--help" => {
show_usage();
return Ok(None);
}
arg => {
if !command_args.config_info.parse_argument(arg, &mut args)? {
return Err(format!("Unknown option {}", arg));
}
}
}
}
command_args.out_path = match out_path {
Some(p) => p.into(),
None => PathBuf::from("./gcc"),
};
return Ok(Some(command_args));
}
}

pub fn run() -> Result<(), String> {
let Some(args) = Args::new()? else {
return Ok(());
};

let result = git_clone("https://github.com/antoyo/gcc", Some(&args.out_path), false)?;
if result.ran_clone {
let gcc_commit = args.config_info.get_gcc_commit()?;
println!("Checking out GCC commit `{}`...", gcc_commit);
run_command_with_output(
&[&"git", &"checkout", &gcc_commit],
Some(Path::new(&result.repo_dir)),
)?;
} else {
println!(
"There is already a GCC folder in `{}`, leaving things as is...",
args.out_path.display()
);
}
Ok(())
}
13 changes: 9 additions & 4 deletions build_system/src/config.rs
Expand Up @@ -192,9 +192,7 @@ impl ConfigInfo {
command
}

fn download_gccjit_if_needed(&mut self) -> Result<(), String> {
let output_dir = Path::new(crate::BUILD_DIR).join("libgccjit");

pub fn get_gcc_commit(&self) -> Result<String, String> {
let commit_hash_file = self.compute_path("libgccjit.version");
let content = fs::read_to_string(&commit_hash_file).map_err(|_| {
format!(
Expand All @@ -212,7 +210,14 @@ impl ConfigInfo {
commit,
));
}
let output_dir = output_dir.join(commit);
Ok(commit.to_string())
}

fn download_gccjit_if_needed(&mut self) -> Result<(), String> {
let output_dir = Path::new(crate::BUILD_DIR).join("libgccjit");
let commit = self.get_gcc_commit()?;

let output_dir = output_dir.join(&commit);
if !output_dir.is_dir() {
std::fs::create_dir_all(&output_dir).map_err(|err| {
format!(
Expand Down
19 changes: 12 additions & 7 deletions build_system/src/main.rs
Expand Up @@ -4,6 +4,7 @@ use std::process;
mod build;
mod cargo;
mod clean;
mod clone_gcc;
mod config;
mod info;
mod prepare;
Expand All @@ -27,19 +28,21 @@ fn usage() {
"\
Available commands for build_system:

cargo : Run cargo command
clean : Run clean command
prepare : Run prepare command
build : Run build command
test : Run test command
info: : Run info command
--help : Show this message"
cargo : Run cargo command
clean : Run clean command
prepare : Run prepare command
build : Run build command
test : Run test command
info : Run info command
clone-gcc : Run clone-gcc command
--help : Show this message"
);
}

pub enum Command {
Cargo,
Clean,
CloneGcc,
Prepare,
Build,
Test,
Expand All @@ -58,6 +61,7 @@ fn main() {
Some("build") => Command::Build,
Some("test") => Command::Test,
Some("info") => Command::Info,
Some("clone-gcc") => Command::CloneGcc,
Some("--help") => {
usage();
process::exit(0);
Expand All @@ -77,6 +81,7 @@ fn main() {
Command::Build => build::run(),
Command::Test => test::run(),
Command::Info => info::run(),
Command::CloneGcc => clone_gcc::run(),
} {
eprintln!("Command failed to run: {e}");
process::exit(1);
Expand Down
4 changes: 2 additions & 2 deletions build_system/src/prepare.rs
@@ -1,6 +1,6 @@
use crate::rustc_info::get_rustc_path;
use crate::utils::{
cargo_install, git_clone, remove_file, run_command, run_command_with_output, walk_dir,
cargo_install, git_clone_root_dir, remove_file, run_command, run_command_with_output, walk_dir,
};

use std::fs;
Expand Down Expand Up @@ -152,7 +152,7 @@ fn clone_and_setup<F>(repo_url: &str, checkout_commit: &str, extra: Option<F>) -
where
F: Fn(&Path) -> Result<(), String>,
{
let clone_result = git_clone(repo_url, Some(&Path::new(crate::BUILD_DIR)), false)?;
let clone_result = git_clone_root_dir(repo_url, &Path::new(crate::BUILD_DIR), false)?;
if !clone_result.ran_clone {
println!("`{}` has already been cloned", clone_result.repo_name);
}
Expand Down
17 changes: 6 additions & 11 deletions build_system/src/test.rs
@@ -1,7 +1,7 @@
use crate::build;
use crate::config::{Channel, ConfigInfo};
use crate::utils::{
get_toolchain, git_clone, remove_file, run_command, run_command_with_env,
get_toolchain, git_clone, git_clone_root_dir, remove_file, run_command, run_command_with_env,
run_command_with_output_and_env, rustc_version_info, split_args, walk_dir,
};

Expand Down Expand Up @@ -487,15 +487,10 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<PathBuf, String> {
);
let rust_dir_path = Path::new(crate::BUILD_DIR).join("rust");
// If the repository was already cloned, command will fail, so doesn't matter.
let _ = run_command_with_output_and_env(
&[
&"git",
&"clone",
&"https://github.com/rust-lang/rust.git",
&rust_dir_path,
],
None,
Some(env),
let _ = git_clone(
"https://github.com/rust-lang/rust.git",
Some(&rust_dir_path),
false,
);
let rust_dir: Option<&Path> = Some(&rust_dir_path);
run_command(&[&"git", &"checkout", &"--", &"tests/"], rust_dir)?;
Expand Down Expand Up @@ -720,7 +715,7 @@ fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> {

let run_tests = |projects_path, iter: &mut dyn Iterator<Item = &&str>| -> Result<(), String> {
for project in iter {
let clone_result = git_clone(project, Some(projects_path), true)?;
let clone_result = git_clone_root_dir(project, projects_path, true)?;
let repo_path = Path::new(&clone_result.repo_dir);
run_cargo_command(&[&"build", &"--release"], Some(repo_path), env, args)?;
run_cargo_command(&[&"test"], Some(repo_path), env, args)?;
Expand Down
57 changes: 45 additions & 12 deletions build_system/src/utils.rs
Expand Up @@ -2,7 +2,7 @@ use std::collections::HashMap;
use std::ffi::OsStr;
use std::fmt::Debug;
use std::fs;
use std::path::Path;
use std::path::{Path, PathBuf};
use std::process::{Command, ExitStatus, Output};

fn get_command_inner(
Expand Down Expand Up @@ -254,20 +254,12 @@ pub struct CloneResult {
pub repo_dir: String,
}

pub fn git_clone(
fn git_clone_inner(
to_clone: &str,
dest: Option<&Path>,
dest: &Path,
shallow_clone: bool,
repo_name: String,
) -> Result<CloneResult, String> {
let repo_name = to_clone.split('/').last().unwrap();
let repo_name = match repo_name.strip_suffix(".git") {
Some(n) => n.to_string(),
None => repo_name.to_string(),
};

let dest = dest
.map(|dest| dest.join(&repo_name))
.unwrap_or_else(|| Path::new(&repo_name).into());
if dest.is_dir() {
return Ok(CloneResult {
ran_clone: false,
Expand All @@ -289,6 +281,47 @@ pub fn git_clone(
})
}

fn get_repo_name(url: &str) -> String {
let repo_name = url.split('/').last().unwrap();
match repo_name.strip_suffix(".git") {
Some(n) => n.to_string(),
None => repo_name.to_string(),
}
}

pub fn git_clone(
to_clone: &str,
dest: Option<&Path>,
shallow_clone: bool,
) -> Result<CloneResult, String> {
let repo_name = get_repo_name(to_clone);
let tmp: PathBuf;

let dest = match dest {
Some(dest) => dest,
None => {
tmp = repo_name.clone().into();
&tmp
}
};
git_clone_inner(to_clone, dest, shallow_clone, repo_name)
}

pub fn git_clone_root_dir(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please add a comment to describe what it does differently than git_clone?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

to_clone: &str,
dest_parent_dir: &Path,
shallow_clone: bool,
) -> Result<CloneResult, String> {
let repo_name = get_repo_name(to_clone);

git_clone_inner(
to_clone,
&dest_parent_dir.join(&repo_name),
shallow_clone,
repo_name,
)
}

pub fn walk_dir<P, D, F>(dir: P, mut dir_cb: D, mut file_cb: F) -> Result<(), String>
where
P: AsRef<Path>,
Expand Down