Skip to content

Commit

Permalink
Prep and cleanup
Browse files Browse the repository at this point in the history
Using anyhow instead of this enum spam mess. Nobody is gonna use this as a library and anyhow makes this much cleaner anyway.

* 0.2.0
* Git clone folder is always named ``repo`` now
* Cloned packages will generate a ``pkg.toml`` file which will be used for saving package info in a user friendly format.
* You can now rebuild packages, it will ignore if the dll has already been generated.
* Prep for cargo support
  • Loading branch information
Vurv78 committed Sep 14, 2021
1 parent 7b17521 commit d834313
Show file tree
Hide file tree
Showing 11 changed files with 158 additions and 69 deletions.
16 changes: 11 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
[package]
name = "gm_binpkg"
version = "0.1.0"
version = "0.2.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
pelite = "0.9.0"

# cli
clap = "3.0.0-beta.4"

colored = "2.0.0"

# targets
cc = "1.0.69" # Compiling C++, Using windows tools
cmake = "0.1.45"

# misc
pelite = "0.9.0"
url = "2.2.2"

serde = { version = "1.0.130", features = ["derive"] }
toml = "0.5.8"

cmake = "0.1.45"
anyhow = "1.0.44"
9 changes: 7 additions & 2 deletions src/pkg/build/gcc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@ use std::{
process::{ExitStatus, Command}
};

pub(crate) fn try_compile(_cache_dir: &PathBuf, main_path: &PathBuf, out_path: &PathBuf) -> Result<ExitStatus, BuildError> {
pub(crate) fn try_compile(cache_dir: &PathBuf, repo_dir: &PathBuf, out_path: &PathBuf) -> Result<ExitStatus, BuildError> {
let main_cpp = repo_dir.join("main.cpp");
if !main_cpp.exists() {
return Err( BuildError::Missing );
}

// Compile main.cpp to main.dll in the package.
let status = Command::new("gcc")
.args( [&main_path.display().to_string(), "-o", &out_path.display().to_string(), "-shared"] )
.args( [&main_cpp.display().to_string(), "-o", &out_path.display().to_string(), "-shared"] )
.status()
.map_err(|x| BuildError::Io(x))?;

Expand Down
36 changes: 18 additions & 18 deletions src/pkg/build/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::Package;
use anyhow::bail;

mod gcc;
mod msbuild;
Expand Down Expand Up @@ -27,33 +28,32 @@ impl std::fmt::Display for BuildError {
}

impl<'a> Package<'a> {
pub fn build(&mut self) -> Result<(), BuildError> {
pub fn build(&mut self) -> anyhow::Result<()>{
let cache_dir = &self.cache;
let repo_dir = &self.cache.join("repo");

if !cache_dir.exists() {
return Err( BuildError::Missing );
if !repo_dir.exists() {
bail!("Repo directory doesn't exist. Not cloned yet?")
}

let out_path = cache_dir
.join("main.dll");

if out_path.exists() {
return Err( BuildError::AlreadyBuilt );
use crate::pkg::process::CompilerTarget::*;
match self.identify_compiler() {
Ok(x) => match x {
Cargo => todo!(),
MSBuild => {
if let Err(why) = msbuild::try_compile(cache_dir, repo_dir, &out_path) {
bail!("{}", why)
}
},
NotFound => bail!("Unknown compiler")
}
Err(why) => bail!(why)
}

let main_path = cache_dir
.join(self.name)
.join("main.cpp");

// TODO: Use .exit_ok()? when it's stabilized.
match msbuild::try_compile( cache_dir, &main_path, &out_path ) {
Ok(_) => println!("Successfully compiled."),
Err(why) => {
return Err(why);
},
}

self.filemap = Some( pelite::FileMap::open(&out_path).map_err(|x| BuildError::Io(x))? );
self.filemap = Some( pelite::FileMap::open(&out_path)? );
Ok(())
}
}
6 changes: 2 additions & 4 deletions src/pkg/build/msbuild.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
use super::BuildError;
use std::path::PathBuf;

pub(crate) fn try_compile(cache_dir: &PathBuf, main_path: &PathBuf, out_path: &PathBuf) -> Result<(), BuildError> {
pub(crate) fn try_compile(cache_dir: &PathBuf, repo_dir: &PathBuf, out_path: &PathBuf) -> Result<(), BuildError> {
// Todo: target should probably not be hardcoded
let msbuild = cc::windows_registry::find_tool("x86_64-pc-windows-msvc", "msbuild")
.ok_or(BuildError::NoMSBuild)?;

let main_dir = main_path.parent().unwrap().display().to_string();

let build_dir = cache_dir.join("msbuild");
std::fs::create_dir_all(&build_dir).map_err( |x| BuildError::Io(x) )?;

let code = msbuild
.to_command()
.args( [&main_dir, "-noLogo", "-m:5", "-verbosity:quiet", &format!("-p:OutDir={}", build_dir.display()), "-p:TargetName=main", "-p:Configuration=Release" ] )
.args( [&repo_dir.display().to_string(), "-noLogo", "-m:5", "-verbosity:quiet", &format!("-p:OutDir={}", build_dir.display()), "-p:TargetName=main", "-p:Configuration=Release" ] )
.status()
.map_err(|x| BuildError::Io(x))?;

Expand Down
2 changes: 1 addition & 1 deletion src/pkg/build/premake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::{
process::{ExitStatus, Command}
};

pub(crate) fn try_compile(_cache_dir: &PathBuf, main_path: &PathBuf, out_path: &PathBuf) -> Result<ExitStatus, BuildError> {
pub(crate) fn try_compile(_cache_dir: &PathBuf, repo_dir: &PathBuf, out_path: &PathBuf) -> Result<ExitStatus, BuildError> {
// Compile main.cpp to main.dll in the package.
let status = Command::new("premake5")
.args( ["vs2019"] )
Expand Down
22 changes: 17 additions & 5 deletions src/pkg/cli/commands/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,23 @@ pub fn clone(x: &ArgMatches) -> Result<(), Box<dyn std::error::Error>>{
repo_url.split("/").last().unwrap()
});

let mut p = Package::new( pkg_name, repo_url, std::env::current_dir()? );
if let Err(why) = p.clone() {
println!( "Errored on clone: {}", why.to_string().red() )
} else {
println!("Cloned");
match url::Url::parse(repo_url) {
Ok(url) => {
match Package::create( pkg_name, url, std::env::current_dir()? ) {
Ok(mut pkg) => {
if let Err(why) = pkg.clone() {
println!( "Errored on clone: {}", why.to_string().red().bold() )
} else {
println!("Cloned {} successfully", repo_url);
}
},

Err(e) => println!("{}", e.to_string().red().bold())
}
},
Err(e) => {
println!("{}: {}", "Invalid URL".red(), e);
}
}

Ok(())
Expand Down
5 changes: 1 addition & 4 deletions src/pkg/cli/commands/init.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
use std::error::Error;

use clap::ArgMatches;
use super::Package;

pub fn init(x: &ArgMatches) -> Result<(), Box<dyn std::error::Error>> {
pub fn init(_: &ArgMatches) -> Result<(), Box<dyn std::error::Error>> {
let pkg_dir = std::env::current_dir()?;

let package_dir = pkg_dir.join("cache"); // Package source install directories, where they're built and then installed to your gmod dir.
Expand Down
2 changes: 0 additions & 2 deletions src/pkg/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ mod commands;
pub(crate) use super::Package;

pub fn process() -> Result<(), Box<dyn std::error::Error>>{
use colored::*;

let opts = clap::clap_app!(myapp =>
(version: "0.1.0")
(author: "Vurv78 <vurvdevelops@gmail.com>")
Expand Down
8 changes: 5 additions & 3 deletions src/pkg/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,18 @@ impl<'a> Package<'a> {
pub fn clone(&mut self) -> Result<(), CloneError> {
let cache_dir = &self.cache;

if cache_dir.exists() {
let git_dir = cache_dir.join("repo");

if git_dir.exists() {
return Err( CloneError::Exists );
}

std::fs::create_dir_all(&cache_dir).map_err(|x| CloneError::Io(x))?;
std::fs::create_dir_all(&git_dir).map_err(|x| CloneError::Io(x))?;

// Clone repo of the package
let status = Command::new("git")
.current_dir( &cache_dir )
.args( ["clone", self.repo, self.name, "--recurse-submodules"] )
.args( ["clone", self.repo_url.as_str(), "repo", "--recurse-submodules"] )
.status()
.map_err(|x| CloneError::Io(x))?;

Expand Down
86 changes: 61 additions & 25 deletions src/pkg/mod.rs
Original file line number Diff line number Diff line change
@@ -1,65 +1,101 @@
pub(crate) mod build;
pub(crate) mod process;
pub(crate) mod clone;

pub(crate) mod cli;

use std::path::PathBuf;

#[derive(Debug)]
pub enum PackageOpen {
NotFound
}
use anyhow::bail;

use std::fmt;
impl fmt::Display for PackageOpen {
fn fmt( &self, f: &mut fmt::Formatter<'_> ) -> fmt::Result {
write!(f, "{}", match self {
PackageOpen::NotFound => "Package not found"
})
}
}
use std::{io::{Read, Write}, path::PathBuf};
use url::Url;

pub struct Package<'a> {
pub name: &'a str, // Todo: Try and make this &'a str again
pub repo: &'a str,
pub name: &'a str,
pub repo_url: Url,
pub mpath: PathBuf, // std::env::current_dir by default

pub(crate) cache: PathBuf,
pub cache: PathBuf,
pub repo: PathBuf,
pub(crate) filemap: Option<pelite::FileMap>
}

use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize)]
struct PackageInfo<'a> {
name: &'a str,
repo_url: &'a str
}

impl<'a> Package<'a> {
pub fn new(name: &'a str, repo_url: &'a str, mpath: PathBuf) -> Self {
pub fn create(name: &'a str, repo_url: Url, mpath: PathBuf) -> anyhow::Result<Self> {
let cache = mpath
.join("cache")
.join(name);

Self {
if cache.exists() {
bail!("Package already exists");
}

let repo_dir = cache.join("repo");

if let Err(why) = std::fs::create_dir_all(&cache) {
bail!("IO Error: {}", why);
}

match std::fs::File::create(cache.join("pkg.toml")) {
Ok(mut f) => {
let a = PackageInfo {
name: name,
repo_url: repo_url.as_str()
};
let b = toml::to_string(&a).unwrap();
f.write_all(b.as_bytes()).unwrap();
}
Err(why) => {
bail!("Error when creating pkg.toml. {}", why);
}
}

Ok(Self {
name: name,
repo: repo_url,
repo_url: repo_url,
mpath: mpath,

cache: cache,
repo: repo_dir,
filemap: None
}
})
}

pub fn open(name: &'a str, mpath: PathBuf) -> Result<Self, PackageOpen> {
pub fn open(name: &'a str, mpath: PathBuf) -> anyhow::Result<Self> {
let cache = mpath
.join("cache")
.join(name);

if !cache.exists() {
return Err( PackageOpen::NotFound )
bail!("Package {} doesn't exist", name)
}

let info = cache.join("pkg.toml");
if !info.exists() {
bail!("Malformed package {}", name);
}

let mut toml = std::fs::File::open(info)?;
let mut buf = String::new();
toml.read_to_string(&mut buf)?;

let data: PackageInfo = toml::from_str(&buf)?;
let repo_url = url::Url::parse( data.repo_url )?;

let repo_dir = cache.join("repo");

Ok(Self {
name: name,
repo: "", // Temporary
repo_url: repo_url,
mpath: mpath,

cache: cache,
repo: repo_dir,
filemap: None
})
}
Expand Down
35 changes: 35 additions & 0 deletions src/pkg/process.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::Package;
use anyhow::bail;

#[derive(Debug)]
pub enum VerifyError {
Expand All @@ -25,6 +26,12 @@ pub type VerifyResult = Result<(), VerifyError>;
const GMOD_DLLOPEN: &str = "gmod13_open";
const GMOD_DLLCLOSE: &str = "gmod13_close";

pub enum CompilerTarget {
MSBuild,
Cargo,
NotFound
}

impl<'a> Package<'a> {
pub fn verify(&self) -> VerifyResult {
if let Some(ref fm) = self.filemap {
Expand All @@ -43,4 +50,32 @@ impl<'a> Package<'a> {
Err( VerifyError::NotBuilt )
}
}

// Tries to find what to compile the package with.
pub fn identify_compiler(&self) -> anyhow::Result<CompilerTarget> {
if !self.cache.exists() {
bail!("Cache does not exist")
}

{
let cargo_toml = self.cache.join("Cargo.toml");
if cargo_toml.exists() {
return Ok(CompilerTarget::Cargo);
}
}

{
for file in std::fs::read_dir(&self.repo)? {
let file = file?;
let path = file.path();
if let Some(ext) = path.extension() {
if ext == "sln" {
return Ok(CompilerTarget::MSBuild);
}
}
}
}

Ok(CompilerTarget::NotFound)
}
}

0 comments on commit d834313

Please sign in to comment.