Skip to content

Commit

Permalink
Reorganize fud2 directory (#1883)
Browse files Browse the repository at this point in the history
* Reorganize `fud2` directory

* add tool metadata

* fix location for README

* reorg driver files

* extra some setup into functions

* create `fud-core` crate

* update desc

* add lisc

* bump version
  • Loading branch information
rachitnigam authored Feb 4, 2024
1 parent e461ede commit e8a4aa1
Show file tree
Hide file tree
Showing 16 changed files with 221 additions and 135 deletions.
36 changes: 18 additions & 18 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ members = [
"tools/data_gen",
"cider-dap",
"fud2",
"fud2/fake",
"fud2/fud-core",
]
exclude = ["site"]

Expand Down
19 changes: 16 additions & 3 deletions fud2/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
[package]
name = "fud2"
version.workspace = true
name = "fud"
version = "0.0.2"
edition.workspace = true
authors.workspace = true
license-file.workspace = true
repository.workspace = true
homepage.workspace = true

keywords = ["build-tool"]
readme = "README.md"
categories = ["build-tool"]
description = "Compiler driver for the Calyx infrastructure"

[dependencies]
fake = { path = "fake" }
fud-core = { path = "fud-core", version = "0.0.2" }
anyhow.workspace = true

[[bin]]
name = "fud2"
path = "src/main.rs"
27 changes: 27 additions & 0 deletions fud2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# `fud`: The Calyx Build Tool

Reimplementation of the [fud][] compiler driver for Calyx.

### Installation

To install from source, run the following from `calyx/fud2`:
```
cargo install --path .
```

This will install the binary `fud2` to the default `cargo` binary location.

### Configuration

The minimal required configuration requires setting the `calyx.base` key so that `fud` knows where the Calyx compiler is. Open the configuration file by running:
```
fud edit-config
```

Add the path to the location of the Calyx compiler:
```toml
[calyx]
base = "<path to calyx repo>"
```

[fud]: https://docs.calyxir.org/fud/index.html
6 changes: 0 additions & 6 deletions fud2/fake/src/lib.rs

This file was deleted.

10 changes: 8 additions & 2 deletions fud2/fake/Cargo.toml → fud2/fud-core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
[package]
name = "fake"
version.workspace = true
name = "fud-core"
version = "0.0.2"
edition.workspace = true
license-file.workspace = true

keywords = ["build-tool"]
readme = "../README.md"
categories = ["build-tool"]
description = "Library for building declarative build tools"

[dependencies]
argh.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion fud2/fake/src/cli.rs → fud2/fud-core/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::config;
use crate::driver::{Driver, Request, StateRef};
use crate::exec::{Driver, Request, StateRef};
use crate::run::Run;
use anyhow::{anyhow, bail};
use argh::FromArgs;
Expand Down
File renamed without changes.
58 changes: 58 additions & 0 deletions fud2/fud-core/src/exec/data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use crate::run;
use cranelift_entity::entity_impl;

/// A State is a type of file that Operations produce or consume.
pub struct State {
/// The name of the state, for the UI.
pub name: String,

/// The file extensions that this state can be represented by.
///
/// The first extension in the list is used when generating a new filename for the state. If
/// the list is empty, this is a "pseudo-state" that doesn't correspond to an actual file.
/// Pseudo-states can only be final outputs; they are appropraite for representing actions that
/// interact directly with the user, for example.
pub extensions: Vec<String>,
}

impl State {
/// Check whether a filename extension indicates this state.
pub fn ext_matches(&self, ext: &str) -> bool {
self.extensions.iter().any(|e| e == ext)
}

/// Is this a "pseudo-state": doesn't correspond to an actual file, and must be an output state?
pub fn is_pseudo(&self) -> bool {
self.extensions.is_empty()
}
}

/// A reference to a State.
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct StateRef(u32);
entity_impl!(StateRef, "state");

/// An Operation transforms files from one State to another.
pub struct Operation {
pub name: String,
pub input: StateRef,
pub output: StateRef,
pub setups: Vec<SetupRef>,
pub emit: Box<dyn run::EmitBuild>,
}

/// A reference to an Operation.
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct OpRef(u32);
entity_impl!(OpRef, "op");

/// A Setup runs at configuration time and produces Ninja machinery for Operations.
pub struct Setup {
pub name: String,
pub emit: Box<dyn run::EmitSetup>,
}

/// A reference to a Setup.
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct SetupRef(u32);
entity_impl!(SetupRef, "setup");
100 changes: 5 additions & 95 deletions fud2/fake/src/driver.rs → fud2/fud-core/src/exec/driver.rs
Original file line number Diff line number Diff line change
@@ -1,75 +1,7 @@
use crate::run;
use super::{OpRef, Operation, Request, Setup, SetupRef, State, StateRef};
use crate::{run, utils};
use camino::{Utf8Path, Utf8PathBuf};
use cranelift_entity::{entity_impl, PrimaryMap, SecondaryMap};
use pathdiff::diff_utf8_paths;

/// A State is a type of file that Operations produce or consume.
pub struct State {
/// The name of the state, for the UI.
pub name: String,

/// The file extensions that this state can be represented by.
///
/// The first extension in the list is used when generating a new filename for the state. If
/// the list is empty, this is a "pseudo-state" that doesn't correspond to an actual file.
/// Pseudo-states can only be final outputs; they are appropraite for representing actions that
/// interact directly with the user, for example.
pub extensions: Vec<String>,
}

/// A reference to a State.
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct StateRef(u32);
entity_impl!(StateRef, "state");

/// An Operation transforms files from one State to another.
pub struct Operation {
pub name: String,
pub input: StateRef,
pub output: StateRef,
pub setups: Vec<SetupRef>,
pub emit: Box<dyn run::EmitBuild>,
}

/// A reference to an Operation.
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct OpRef(u32);
entity_impl!(OpRef, "op");

/// A Setup runs at configuration time and produces Ninja machinery for Operations.
pub struct Setup {
pub name: String,
pub emit: Box<dyn run::EmitSetup>,
}

/// A reference to a Setup.
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct SetupRef(u32);
entity_impl!(SetupRef, "setup");

impl State {
/// Check whether a filename extension indicates this state.
fn ext_matches(&self, ext: &str) -> bool {
self.extensions.iter().any(|e| e == ext)
}

/// Is this a "pseudo-state": doesn't correspond to an actual file, and must be an output state?
fn is_pseudo(&self) -> bool {
self.extensions.is_empty()
}
}

/// Get a version of `path` that works when the working directory is `base`. This is
/// opportunistically a relative path, but we can always fall back to an absolute path to make sure
/// the path still works.
pub fn relative_path(path: &Utf8Path, base: &Utf8Path) -> Utf8PathBuf {
match diff_utf8_paths(path, base) {
Some(p) => p,
None => path
.canonicalize_utf8()
.expect("could not get absolute path"),
}
}
use cranelift_entity::{PrimaryMap, SecondaryMap};

#[derive(PartialEq)]
enum Destination {
Expand Down Expand Up @@ -196,7 +128,7 @@ impl Driver {

// Get the initial input filename and the stem to use to generate all intermediate filenames.
let (stdin, start_file) = match req.start_file {
Some(path) => (false, relative_path(&path, &req.workdir)),
Some(path) => (false, utils::relative_path(&path, &req.workdir)),
None => (true, "stdin".into()),
};
let stem = start_file.file_stem().unwrap();
Expand All @@ -211,7 +143,7 @@ impl Driver {
let stdout = if let Some(end_file) = req.end_file {
// TODO Can we just avoid generating the unused filename in the first place?
let last_step = steps.last_mut().expect("no steps");
last_step.1 = relative_path(&end_file, &req.workdir);
last_step.1 = utils::relative_path(&end_file, &req.workdir);
false
} else {
// Print to stdout if the last state is a real (non-pseudo) state.
Expand Down Expand Up @@ -350,28 +282,6 @@ impl DriverBuilder {
}
}

/// A request to the Driver directing it what to build.
#[derive(Debug)]
pub struct Request {
/// The input format.
pub start_state: StateRef,

/// The output format to produce.
pub end_state: StateRef,

/// The filename to read the input from, or None to read from stdin.
pub start_file: Option<Utf8PathBuf>,

/// The filename to write the output to, or None to print to stdout.
pub end_file: Option<Utf8PathBuf>,

/// A sequence of operators to route the conversion through.
pub through: Vec<OpRef>,

/// The working directory for the build.
pub workdir: Utf8PathBuf,
}

#[derive(Debug)]
pub struct Plan {
/// The input to the first step.
Expand Down
8 changes: 8 additions & 0 deletions fud2/fud-core/src/exec/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
mod data;
mod driver;
mod request;

pub use data::{OpRef, SetupRef, StateRef};
pub(super) use data::{Operation, Setup, State};
pub use driver::{Driver, DriverBuilder, Plan};
pub use request::Request;
24 changes: 24 additions & 0 deletions fud2/fud-core/src/exec/request.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use super::{OpRef, StateRef};
use camino::Utf8PathBuf;

/// A request to the Driver directing it what to build.
#[derive(Debug)]
pub struct Request {
/// The input format.
pub start_state: StateRef,

/// The output format to produce.
pub end_state: StateRef,

/// The filename to read the input from, or None to read from stdin.
pub start_file: Option<Utf8PathBuf>,

/// The filename to write the output to, or None to print to stdout.
pub end_file: Option<Utf8PathBuf>,

/// A sequence of operators to route the conversion through.
pub through: Vec<OpRef>,

/// The working directory for the build.
pub workdir: Utf8PathBuf,
}
7 changes: 7 additions & 0 deletions fud2/fud-core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pub mod cli;
pub mod config;
pub mod exec;
pub mod run;
pub mod utils;

pub use exec::{Driver, DriverBuilder};
3 changes: 2 additions & 1 deletion fud2/fake/src/run.rs → fud2/fud-core/src/run.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::config;
use crate::driver::{relative_path, Driver, OpRef, Plan, SetupRef, StateRef};
use crate::exec::{Driver, OpRef, Plan, SetupRef, StateRef};
use crate::utils::relative_path;
use camino::{Utf8Path, Utf8PathBuf};
use std::collections::{HashMap, HashSet};
use std::io::Write;
Expand Down
14 changes: 14 additions & 0 deletions fud2/fud-core/src/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use camino::{Utf8Path, Utf8PathBuf};
use pathdiff::diff_utf8_paths;

/// Get a version of `path` that works when the working directory is `base`. This is
/// opportunistically a relative path, but we can always fall back to an absolute path to make sure
/// the path still works.
pub fn relative_path(path: &Utf8Path, base: &Utf8Path) -> Utf8PathBuf {
match diff_utf8_paths(path, base) {
Some(p) => p,
None => path
.canonicalize_utf8()
.expect("could not get absolute path"),
}
}
Loading

0 comments on commit e8a4aa1

Please sign in to comment.