7 Commits

Author SHA1 Message Date
e25c27f082 wip 2026-03-23 11:43:22 -05:00
f30432c1db Cleanup some code that should've been done earlier (#7)
Reviewed-on: http://192.168.1.227:3000/sfrembling/pallet/pulls/7
Co-authored-by: godsfryingpan <sfrembling@gmail.com>
Co-committed-by: godsfryingpan <sfrembling@gmail.com>
2026-03-23 10:27:26 -06:00
1b34dee81e Update README.md 2026-03-23 10:13:26 -06:00
46abec1237 Increment version 2026-03-23 11:09:19 -05:00
49eaf6dbfc Enable compilers other than gcc (#6)
issue: #1
Reviewed-on: http://192.168.1.227:3000/sfrembling/pallet/pulls/6
Co-authored-by: godsfryingpan <sfrembling@gmail.com>
Co-committed-by: godsfryingpan <sfrembling@gmail.com>
2026-03-23 10:08:35 -06:00
02009762c1 update PKGBUILD with gcc as dep (#5)
issue: #3
Reviewed-on: http://192.168.1.227:3000/sfrembling/pallet/pulls/5
Co-authored-by: godsfryingpan <sfrembling@gmail.com>
Co-committed-by: godsfryingpan <sfrembling@gmail.com>
2026-03-23 09:57:14 -06:00
e52ad0bc24 add --force-recompile flag (#4)
issue: #2
Reviewed-on: http://192.168.1.227:3000/sfrembling/pallet/pulls/4
Co-authored-by: godsfryingpan <sfrembling@gmail.com>
Co-committed-by: godsfryingpan <sfrembling@gmail.com>
2026-03-23 09:55:03 -06:00
7 changed files with 97 additions and 40 deletions

2
Cargo.lock generated
View File

@@ -247,7 +247,7 @@ checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
[[package]]
name = "pallet"
version = "1.0.5"
version = "1.0.6"
dependencies = [
"clap",
"clap_complete",

View File

@@ -1,6 +1,6 @@
[package]
name = "pallet"
version = "1.0.5"
version = "1.0.6"
edition = "2024"
description = "A project manager and build system for C inspired by Rust's Cargo"

View File

@@ -1,12 +1,12 @@
# Maintainer: Shea Frembling <sfrembling@gmail.com>
pkgname=pallet
pkgver=1.0.5
pkgver=1.0.6
pkgrel=1
pkgdesc="A simple C project manager inspired by Cargo"
arch=('x86_64')
url=""
license=('MIT')
depends=()
depends=('gcc')
makedepends=('rust' 'cargo')
source=()

View File

@@ -6,11 +6,29 @@ This is a toy project not meant to be taken very seriously.
## Requirements for Use
[GCC](https://en.wikipedia.org/wiki/GNU_Compiler_Collection) is required as it is currently the back-end tool used to compile the C code.
[GCC](https://en.wikipedia.org/wiki/GNU_Compiler_Collection) is recommended as the compiler installed for `Pallet` projects.
This tool calls `gcc` internally, so without it, it would fail.
You can define a different `gcc` compatible compiler instead per-project by editing `Pallet.toml`:
At some point I would like to update `Pallet.toml` to instead allow more configuring of how the build should be performed.
```toml
name = "my-app"
default_build = "debug"
compiler = "clang"
[[build]]
name = "debug"
args = [
"-g",
"-O0",
]
[[build]]
name = "release"
args = [
"-DNDEBUG",
"-O3",
]
```
## Usage

View File

@@ -9,6 +9,7 @@ use colored::Colorize;
use glob::glob;
const MAIN_C: &str = include_str!("templates/main.c");
const TEST_C: &str = include_str!("templates/it_works.c");
const GITIGNORE: &str = "target/";
#[derive(clap::Parser)]
@@ -29,6 +30,9 @@ enum Subcommand {
Init,
/// Run the local project
Run {
/// Force recompilation of the project
#[arg(long, short)]
force_recompile: bool,
/// The build mode to use
mode: Option<String>,
/// Arguments to pass to the project binary
@@ -37,6 +41,9 @@ enum Subcommand {
},
/// Build the local project
Build {
/// Force recompilation of the project
#[arg(long, short)]
force_recompile: bool,
/// The build mode to use
mode: Option<String>,
},
@@ -47,6 +54,11 @@ enum Subcommand {
#[clap(subcommand)]
command: UtilSubcommand,
},
/// Run tests in your project
Test {
/// The build mode to use
mode: Option<String>,
},
/// List available build modes
List,
}
@@ -72,47 +84,47 @@ enum ShellCompletions {
impl App {
pub fn run(self) {
match self.command {
Subcommand::New { name } => match create_project(&name) {
Err(e) => {
Subcommand::New { name } => {
if let Err(e) = create_project(&name) {
eprintln!("Error creating project '{name}': {e}");
std::process::exit(1);
}
_ => {}
},
Subcommand::Init => match create_project(".") {
Err(e) => {
}
Subcommand::Init => {
if let Err(e) = create_project(".") {
eprintln!("Error initializing project: {e}");
std::process::exit(1);
}
_ => {}
},
Subcommand::Run { mode, args } => {
match build(&mode) {
Err(e) => {
}
Subcommand::Run {
mode,
args,
force_recompile,
} => {
if let Err(e) = build(&mode, force_recompile) {
eprintln!("Error building project: {e}");
std::process::exit(1);
}
_ => {}
};
if let Err(e) = run(&mode, args) {
eprintln!("Error running project: {e}");
std::process::exit(1);
}
}
Subcommand::Build { mode } => match build(&mode) {
Err(e) => {
Subcommand::Build {
mode,
force_recompile,
} => {
if let Err(e) = build(&mode, force_recompile) {
eprintln!("Error building project: {e}");
std::process::exit(1);
}
_ => {}
},
Subcommand::Clean => match clean() {
Err(e) => {
}
Subcommand::Clean => {
if let Err(e) = clean() {
eprintln!("Error cleaning project: {e}");
std::process::exit(1);
}
_ => {}
},
}
Subcommand::Utils { command } => match command {
UtilSubcommand::Completions { shell } => {
let name = env!("CARGO_PKG_NAME");
@@ -145,16 +157,29 @@ impl App {
}
}
},
Subcommand::List => match list() {
Err(e) => {
Subcommand::List => {
if let Err(e) = list() {
eprintln!("Error listing build profiles: {e}");
std::process::exit(1);
}
_ => {}
},
}
Subcommand::Test { mode } => {
if let Err(e) = test(mode) {
eprintln!("Error running tests: {e}");
std::process::exit(1);
}
}
}
}
}
fn test(mode: Option<String>) -> std::io::Result<()> {
for entry in glob("src/tests/*.c").expect("a valid glob pattern") {
if let Ok(file) = entry {}
}
Ok(())
}
fn list() -> std::io::Result<()> {
let conf = get_config().ok_or(std::io::Error::new(
@@ -220,7 +245,7 @@ fn get_config() -> Option<crate::config::Config> {
toml::from_str(&raw).ok()
}
fn build(mode: &Option<String>) -> std::io::Result<()> {
fn build(mode: &Option<String>, force_recompile: bool) -> std::io::Result<()> {
let conf = match get_config() {
Some(conf) => conf,
None => {
@@ -249,7 +274,7 @@ fn build(mode: &Option<String>) -> std::io::Result<()> {
let old_compute_path = PathBuf::from(format!("target/{}/.build_hash", build_config.name));
if old_compute_path.exists() {
if old_compute_path.exists() && !force_recompile {
let text = std::fs::read_to_string(old_compute_path)?;
if hash.trim() == text.trim() {
@@ -261,7 +286,7 @@ fn build(mode: &Option<String>) -> std::io::Result<()> {
}
}
let mut command = Command::new("gcc");
let mut command = Command::new(conf.compiler.as_deref().unwrap_or("gcc"));
for arg in &build_config.args {
command.arg(arg);
@@ -279,9 +304,14 @@ fn build(mode: &Option<String>) -> std::io::Result<()> {
.arg("-o")
.arg(format!("target/{}/{}", build_config.name, conf.name));
let mut child = command.spawn()?;
let status = command.status()?;
child.wait()?;
if !status.success() {
return Err(std::io::Error::new(
std::io::ErrorKind::Other,
format!("compiler exited with status {status}"),
));
}
std::fs::write(format!("target/{}/.build_hash", build_config.name), hash)?;
@@ -347,7 +377,7 @@ fn run(mode: &Option<String>, args: Option<Vec<String>>) -> std::io::Result<()>
}
fn clean() -> std::io::Result<()> {
if let None = get_config() {
if get_config().is_none() {
return Err(std::io::Error::new(
std::io::ErrorKind::NotFound,
"no Pallet.toml found in local dir",

View File

@@ -1,5 +1,7 @@
#[derive(serde::Deserialize, serde::Serialize, Default)]
pub struct Config {
/// The C compiler to use (defaults to "gcc")
pub compiler: Option<String>,
/// The name of the output binary
pub name: String,
/// The default build to use

7
src/templates/it_works.c Normal file
View File

@@ -0,0 +1,7 @@
#include <assert.h>
int main() {
assert((1 + 1) == 2);
return 0;
}