Skip to content
This repository has been archived by the owner on Apr 14, 2023. It is now read-only.

Commit

Permalink
Make the compiler use local source code
Browse files Browse the repository at this point in the history
Now the source code is compressed and statically linked into the binary, so there is no need to git clone it from github anymore, both removing version issues and the git dependency.
  • Loading branch information
Alonely0 committed Dec 29, 2021
1 parent 7aafd1c commit 67ea61e
Show file tree
Hide file tree
Showing 12 changed files with 81 additions and 43 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
target/
test/
Cargo.lock

code.tar.gz
2 changes: 1 addition & 1 deletion compiled_voila/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ version = "0.1.0"
edition = "2021"

[dependencies]
voila = {path = "../voila"}
voila = {path = "../voila"}
4 changes: 4 additions & 0 deletions compiled_voila/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
fn main() {
// the use of the `env!()` macro instead of
// its `option_env!()` counterpart is on purpose,
// so if the data needed to run is not provided, a compile-time
// error will be thrown instead of a runtime one.
if let Err(ref e) = voila::exec(
str_to_vec_u8(env!("v_code")).into(), // into() automatically deserializes the data
std::path::PathBuf::from(env!("v_path")),
Expand Down
8 changes: 6 additions & 2 deletions voila/Cargo.toml
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ keywords = [

[dependencies]
md5 = "0.7.0"
sha2 = "0.10.0"
sha-1 = "0.10.0"
sha2 = "0.9.5"
sha-1 = "0.9.7"
walkdir = "2.3.2"
regex = "1.5.4"
structopt = "0.3.23"
Expand All @@ -51,6 +51,10 @@ serde = "1.0.130"
serde_derive = "1.0.130"
bincode = "1.3.3"

[build-dependencies]
tar = "0.4.37"
flate2 = "1.0.21"

[dev-dependencies]
criterion = "0.3.5"

Expand Down
27 changes: 27 additions & 0 deletions voila/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use flate2::write::GzEncoder;
use flate2::Compression;
use std::env::current_dir;
use std::fs::File;

const COMPILE_ASSETS: [&str; 4] = ["voila", "compiled_voila", "Cargo.toml", "Cargo.lock"];

fn main() {
let src = &current_dir().expect("Can't open current directory");
let src = src.parent().unwrap();
let dest = File::create(format!("{}/code.tar.gz", src.to_str().unwrap()))
.expect("Can't write to current directory");
println!("{}/code.tar.gz", src.to_str().unwrap());
let encoder = GzEncoder::new(dest, Compression::default());
let mut tar = tar::Builder::new(encoder);
for a in COMPILE_ASSETS {
let p = src.join(a);
if p.is_dir() {
tar.append_dir_all(a, p)
.expect("Can't read current directory");
} else {
tar.append_path_with_name(p, a)
.expect("Can't read current directory");
}
}
tar.finish().unwrap();
}
5 changes: 3 additions & 2 deletions voila/src/ast/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,10 +410,11 @@ fn gzc(source: &str, dest: &str) -> Result<(), io::Error> {
let mut tar = tar::Builder::new(encoder);
let source = PathBuf::from(source);
if source.is_dir() {
tar.append_dir_all(source.clone(), source)
tar.append_dir_all(source.clone(), source)?;
} else {
tar.append_path(source)
tar.append_path(source)?;
}
tar.finish()
}

fn gzd(source: &str, dest: &str) -> Result<(), io::Error> {
Expand Down
1 change: 1 addition & 0 deletions voila/src/ast/lookup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ trait Specifier<T: Sized, const O: usize> {
fn detect(source: &str) -> Option<T>;
}

#[allow(clippy::enum_variant_names)]
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SizeLabel {
TeraBytes,
Expand Down
6 changes: 0 additions & 6 deletions voila/src/ast/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,3 @@ pub fn run_script(
// });
// }
}

impl<'source> From<Vec<u8>> for Script<'source> {
fn from(s: Vec<u8>) -> Self {
bincode::deserialize(&s[..]).unwrap()
}
}
15 changes: 15 additions & 0 deletions voila/src/bytecode.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use crate::ast::Script;

pub type VoilaByteCode = Vec<u8>;

impl<'source> From<Script<'source>> for VoilaByteCode {
fn from(code: Script<'source>) -> Self {
bincode::serialize(&code).unwrap()
}
}

impl<'source> From<VoilaByteCode> for Script<'source> {
fn from(s: VoilaByteCode) -> Self {
bincode::deserialize(&s[..]).unwrap()
}
}
51 changes: 22 additions & 29 deletions voila/src/compiler.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,36 @@
use flate2::read::GzDecoder;
use std::env;
use std::fs;
use std::path::Path;
use std::process;
use tar::Archive;

/// Compiles with cargo nightly a crate in a given path
/// providing variables needed to run voila (e.g script's code)
/// leaving the compiled binary in the current directory.
pub fn compile(vars: [&str; 3]) -> Result<(), &str> {
// save current dir
let pwd = env::current_dir().unwrap();
// Error messages
const COMPILER_ERR_MSG: &str = "Could not compile. Make sure Cargo (a wrapper over rust's compiler) is installed, it's in your PATH and the nightly toolchain is installed:\nhttps://www.rust-lang.org/tools/install";
const TEMPDIR_ERR_MSG: &str = "Can't write to temporary directory";
const ENV_READ_ERR_MSG: &str = "Can't access current directory";
const ENV_WRITE_ERR_MSG: &str = "Can't change environment";

// set git clone path
/// Embeds a Voila Script into a binary through
/// the `compiled_voila` crate. The source is
/// statically linked into the binary.
pub fn compile(vars: [&str; 3]) -> Result<(), &str> {
let source = include_bytes!("../../code.tar.gz").as_ref();
let pwd = env::current_dir().map_err(|_| ENV_READ_ERR_MSG)?;
let target_dir = &get_target_dir();
let mut archive = Archive::new(GzDecoder::new(source));

// delete target dir (if exists)
// prepare target dir
if Path::new(target_dir).exists() {
fs::remove_dir_all(target_dir).unwrap();
}

// clone repo
const GIT_ERR_MSG: &str = "Could not download required files to compile the code. Make sure git is installed and in your PATH:\nhttps://git-scm.com/";
let git_exit_status = process::Command::new("git")
.arg("clone")
.arg("https://github.com/Alonely0/Voila.git")
.arg(target_dir)
.status()
.map_err(|_| GIT_ERR_MSG)?
.code()
.unwrap_or(0);

if git_exit_status > 0 {
return Err(GIT_ERR_MSG);
fs::remove_dir_all(target_dir).map_err(|_| TEMPDIR_ERR_MSG)?;
}
fs::create_dir_all(target_dir).map_err(|_| TEMPDIR_ERR_MSG)?;
archive.unpack(target_dir).map_err(|_| TEMPDIR_ERR_MSG)?;

// set dir so cargo knows where to run
env::set_current_dir(target_dir).unwrap();
env::set_current_dir(target_dir).map_err(|_| ENV_WRITE_ERR_MSG)?;

// launch compiler & get exit code
const COMPILER_ERR_MSG: &str = "Could not compile. Make sure Cargo (a wrapper over rust's compiler) is installed, it's in your PATH and the nightly toolchain is installed:\nhttps://www.rust-lang.org/tools/install";
let compiler_exit_status = process::Command::new("cargo")
.env("v_code", vars[0])
.env("v_path", vars[1])
Expand All @@ -54,10 +47,10 @@ pub fn compile(vars: [&str; 3]) -> Result<(), &str> {
.unwrap_or(0);

// restore to the actual current directory
env::set_current_dir(pwd).unwrap();
env::set_current_dir(pwd).map_err(|_| ENV_WRITE_ERR_MSG)?;

// remove temporary files
fs::remove_dir_all(target_dir).unwrap();
// fs::remove_dir_all(target_dir).map_err(|_| "Can't write to temporary directory")?;

if compiler_exit_status > 0 {
Err(COMPILER_ERR_MSG)
Expand All @@ -66,7 +59,7 @@ pub fn compile(vars: [&str; 3]) -> Result<(), &str> {
}
}

fn get_target_dir() -> String {
pub fn get_target_dir() -> String {
#[cfg(unix)]
return "/tmp/Voila".to_string();
#[cfg(windows)]
Expand Down
2 changes: 1 addition & 1 deletion voila/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#![forbid(unsafe_code)] // unsafe code makes ferris get nervous
#![feature(format_args_capture)]
#![feature(once_cell)]
#![feature(decl_macro)]
#![feature(never_type)]
Expand All @@ -8,6 +7,7 @@
use std::error::Error;

mod ast;
mod bytecode;
mod cli;
mod error;
mod interpreter;
Expand Down
1 change: 0 additions & 1 deletion voila/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#![forbid(unsafe_code)] // unsafe code makes ferris get nervous
#![feature(format_args_capture)]
#![feature(decl_macro)]
#![allow(clippy::upper_case_acronyms)]

Expand Down

0 comments on commit 67ea61e

Please sign in to comment.