Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEAT: Use Ninja instead of Make [WIP] #3

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 9 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ automatically when some dependencies are updated. The goal of Gird is to combine
the following features.

- A simple, expressive, and intuitive rule definition and execution scheme very
close to Make.
close to that of Make.
- Configuration in Python, allowing straightforward and familiar usage, without
the need for a dedicated rule definition syntax.
- Ability to take advantage of Python's flexibility and possibility to easily
Expand All @@ -25,13 +25,8 @@ the following features.
Install Gird from PyPI with `pip install gird`, or from sources with
`pip install .`.

### Requirements

Gird is built & tested for Python versions 3.8 & above.

Gird requires [Make][make] to be available on the system. Most versions of Make
will do, as long as they support the `.PHONY` & `.ONESHELL` special targets.

## Usage

Define "rules" in *girdfile.py*. Depending on the composition of the rule
Expand All @@ -40,7 +35,7 @@ definition, a rule can, for example,
- define a recipe to run a task, e.g., to update a target file,
- define prerequisites for the target, such as dependency files or other rules,
and
- use Python functions for more complex target & recipe functionality.
- use Python functions for more complex dependency & recipe functionality.

A rule is invoked by `gird <target_name>`. To list all targets, run
`gird --list`.
Expand All @@ -67,8 +62,8 @@ rule_pytest = rule(
rule_check_formatting = rule(
target=Phony("check_formatting"),
recipe=[
"black --check gird scripts girdfile.py",
"isort --check gird scripts girdfile.py",
f"black --check gird scripts girdfile.py",
f"isort --check gird scripts girdfile.py",
],
help="Check formatting with Black & isort.",
)
Expand All @@ -93,11 +88,9 @@ rule(

rule(
target=Path("README.md"),
deps=list(
chain(
*(Path(path).iterdir() for path in ("scripts", "gird")),
[Path("girdfile.py")],
),
deps=chain(
*(Path(path).iterdir() for path in ("scripts", "gird")),
[Path("girdfile.py")],
),
recipe=render_readme,
help="Render README.md based on README_template.md.",
Expand Down Expand Up @@ -132,7 +125,7 @@ test
- Check that README.md is updated based on README_template.md.
README.md
Render README.md based on README_template.md.
dist/gird-1.2.5-py3-none-any.whl
dist/gird-1.3.0-py3-none-any.whl
Build distribution packages for the current version.
publish
Publish packages of the current version to PyPI.
Expand All @@ -152,7 +145,7 @@ wheel = pathlib.Path("package.whl")
rule_build = gird.rule(
target=wheel,
deps=pathlib.Path("module.py"),
recipe=f"python -m build --wheel",
recipe="python -m build --wheel",
)
```

Expand Down Expand Up @@ -252,9 +245,3 @@ rules = [
]

```

## Implementation of Gird

Internally, Gird generates Makefiles & uses Make to run tasks, but interacting
with Make in any way isn't obligatory when using Gird. In the future, Make as a
dependency of Gird might be replaced altogether.
11 changes: 7 additions & 4 deletions gird/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@
SubRecipe = Union[str, Callable[[Any], Any]]


class Phony(str):
def __init__(self, value):
if not value:
class Phony:
def __init__(self, name):
if not name:
raise ValueError("The name of a Phony target must not be empty.")
super().__init__()
self.name = str(name)

def __str__(self) -> str:
return self.name


@dataclasses.dataclass
Expand Down
6 changes: 5 additions & 1 deletion gird/dependency.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def __call__(self):

This function should be called at most once when any rule is executed.
"""
tag_path = get_gird_path_tmp() / self.name
tag_path = self.tag_path
tag_path.touch()
updated = self.function()
if not updated:
Expand All @@ -40,6 +40,10 @@ def function(self):
def name(self):
return self.function.__name__

@property
def tag_path(self):
return get_gird_path_tmp() / self.name


# "Decorative" alias
dep = DependencyFunction
25 changes: 13 additions & 12 deletions gird/gird.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from .common import Rule
from .girdfile import import_girdfile
from .girdpath import get_gird_path_run, get_gird_path_tmp, init_gird_path
from .makefile import write_makefiles
from .ninjaconvert import write_buildfiles


def parse_args() -> argparse.Namespace:
Expand Down Expand Up @@ -54,19 +54,19 @@ def parse_args() -> argparse.Namespace:

def run_target(target: str):
"""Run a target. Call sys.exit(returncode) in case of non-zero return code."""
makefile_dir = get_gird_path_tmp()
gird_path_tmp = get_gird_path_tmp()
gird_path_run = get_gird_path_run()

args = [
"make",
"ninja",
target,
"-C",
str(gird_path_run.resolve()),
"-f",
str((makefile_dir / "Makefile1").resolve()),
str((gird_path_tmp / "build1.ninja").resolve()),
]

print(f"gird: Executing target '{target}'.")
print(f"gird: Executing target '{target}'.", flush=True)

process = subprocess.run(
args,
Expand All @@ -75,12 +75,15 @@ def run_target(target: str):

if process.returncode != 0:
print(
f"gird: Execution of target '{target}' returned with error. Possible "
f"output & error messages should be visible above."
(
f"gird: Execution of target '{target}' returned with error. "
"Possible output & error messages should be visible above."
),
flush=True,
)
sys.exit(process.returncode)
else:
print(f"gird: Target '{target}' was successfully executed.")
print(f"gird: Target '{target}' was successfully executed.", flush=True)


def list_rules(rules: Iterable[Rule]):
Expand All @@ -99,8 +102,6 @@ def main():
rules = import_girdfile(args.girdfile)
if args.list:
list_rules(rules)
write_makefiles(rules)
write_buildfiles(rules)
if args.target:
run_target(
args.target,
)
run_target(args.target)
Loading