Skip to content

Commit

Permalink
Allow configuring binary output, generate command
Browse files Browse the repository at this point in the history
Resolves #7 by adding a `generate` command which generates a basic makefile to accomplish what `cpkg build` does.

This also comes with a new configuration, being [package.bin], that allows you to change where the package will be output. By default, it is now `target/<package.name>`, while it previously was `target/out`.
  • Loading branch information
DvvCz committed Apr 14, 2024
1 parent fa78a7d commit f98f13e
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 9 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "cpkg"
description = "A dead simple C package manager."
version = "0.6.5"
version = "0.7.0"
edition = "2021"

authors = ["David Cruz <codebycruz@gmail.com>"]
Expand Down
17 changes: 12 additions & 5 deletions src/compiler.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,34 @@
pub trait Compiler {
fn compile(&self, file: &std::path::Path, deps: &[&std::path::Path], to: &std::path::Path, flags: &[String]) -> anyhow::Result<()>;
fn compile(&self, main: &std::path::Path, deps: &[&std::path::Path], to: &std::path::Path, flags: &[String]) -> anyhow::Result<()>;
fn get_compile_command(&self, main: &std::path::Path, deps: &[&std::path::Path], to: &std::path::Path, flags: &[String]) -> std::process::Command;
}

pub struct Gcc {
path: std::path::PathBuf
}

impl Compiler for Gcc {
fn compile(&self, file: &std::path::Path, deps: &[&std::path::Path], to: &std::path::Path, flags: &[String]) -> anyhow::Result<()> {
fn get_compile_command(&self, main: &std::path::Path, deps: &[&std::path::Path], to: &std::path::Path, flags: &[String]) -> std::process::Command {
let mut cmd = std::process::Command::new(&self.path);

let mut cmd = cmd
.arg(file)
cmd
.arg(main)
.arg("-o")
.arg(to)
.args(flags);

for dep in deps { // Include dependency folder
cmd = cmd
cmd
.arg("-I")
.arg(dep);
}

cmd
}

fn compile(&self, file: &std::path::Path, deps: &[&std::path::Path], to: &std::path::Path, flags: &[String]) -> anyhow::Result<()> {
let mut cmd = self.get_compile_command(file, deps, to, flags);

let e = cmd
.spawn()?
.wait()?;
Expand Down
85 changes: 82 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,27 @@ enum Commands {
open: bool
},

#[command(about = "Formats the project's code using clang-format, if available.\n\x1b[36m")]
#[command(about = "Formats the project's code using clang-format, if available.\x1b[33m")]
Format,

#[command(about = "Generates a project file for use with other build managers.\n\x1b[36m")]
Generate {
#[command(subcommand)]
kind: GenerateCommand
},

#[command(about = "Creates a REPL with gcc or clang, if available.\x1b[36m")]
Repl,

#[command(about = "Updates to the latest version of cpkg.\n\x1b[35m")]
Upgrade
}

#[derive(Subcommand)]
enum GenerateCommand {
Make,
}

fn init_project(proj: &std::path::Path) -> std::io::Result<()> {
let src = proj.join("src");
std::fs::create_dir(&src)?;
Expand Down Expand Up @@ -115,6 +126,8 @@ struct Config {
#[derive(serde::Deserialize)]
struct ConfigPackage {
name: String,
/// Optional location to output the target binary
bin: Option<String>
}

#[derive(serde::Deserialize)]
Expand Down Expand Up @@ -282,7 +295,12 @@ fn main() -> anyhow::Result<()> {

let now = std::time::Instant::now();

let out = target.join("out");
let out = if let Some(p) = config.package.bin {
std::path::PathBuf::from(p)
} else {
target.join(config.package.name)
};

let backend = compiler::try_locate()?;
backend.compile(&main, &[src], &out, &flags)?;

Expand Down Expand Up @@ -334,7 +352,11 @@ fn main() -> anyhow::Result<()> {
std::fs::create_dir(target)?;
}

let out = target.join("out");
let out = if let Some(p) = config.package.bin {
std::path::PathBuf::from(p)
} else {
target.join(config.package.name)
};

let b = compiler::try_locate()?;
b.compile(&main, &[src], &out, &flags)?;
Expand Down Expand Up @@ -411,6 +433,63 @@ fn main() -> anyhow::Result<()> {
println!("Formatted code in {}s", now.elapsed().as_secs_f32());
},


Commands::Generate { kind } => {
match kind {
GenerateCommand::Make => {
let config = std::path::Path::new("cpkg.toml");
if !config.exists() {
anyhow::bail!("No cpkg.toml detected, this doesn't seem to be a valid project.");
}

let config = std::fs::read_to_string(config)?;
let config = toml::from_str::<Config>(&config)?;

let flags = config
.compiler
.and_then(|c| c.flags)
.unwrap_or(vec![]);

let src = std::path::Path::new("src");

let main = src.join("main.c");
if !main.exists() {
anyhow::bail!("No entrypoint found (create src/main.c)");
}

let target = std::path::Path::new("target");
if !target.exists() {
std::fs::create_dir(target)?;
}

let now = std::time::Instant::now();

let out = if let Some(p) = config.package.bin {
std::path::PathBuf::from(p)
} else {
target.join(config.package.name)
};

let backend = compiler::try_locate()?;

let cmd = backend.get_compile_command(&main, &[], &out, &flags);

let cc = cmd.get_program();

let make = indoc::formatdoc! {"
CC = {cc:?}
main:
{cmd:?}
"};

std::fs::write("Makefile", make)?;

println!("Generated Makefile in {}s", now.elapsed().as_secs_f32());
}
}
},

Commands::Repl => {
use std::io::Write;

Expand Down

0 comments on commit f98f13e

Please sign in to comment.