Skip to main content

A make-like DI-based Python build system.

Project description

Panifex: A Python Build System

Overview

Panifex is a Python build system that easily allows you to tie together various parts of a multi-stage build and to create reusable recipes. It is a good replacement for make and related tools.

Example Usage

The following example defines a bake.py script that builds a tetris game from its project root directory:

#!/usr/bin/env python
from pathlib import Path
from panifex import build, sh

sh.env(CC="clang", CFLAGS=("-g", "-I./include"), LDFLAGS=("-lncurses", "-lpanel"))

def compile(src):
    return sh(
        "{CC} -c {CFLAGS} {input} -o {output}",
        input=src,
        output=Path(src).with_suffix(".o"),
    )

def link(executable, objects):
    return sh("{CC} {LDFLAGS} {input} -o {output}", input=objects, output=executable)

@build
class ntetris2:
    def sources(self):
        return Path.cwd().glob("**/*.c")

    def objects(self, sources):
        return [compile(src) for src in sources]

    def executable(self, objects):
        return link("ntetris2", objects)

In the above example, the following usage patterns are presented:

  • build and sh are imported from panifex.
    • build is a decorator function which wraps a class that defines the targets for the build. Each named function in the class is a build target that can be invoked directly from the bake.py script. All targets are built if none are provided.
    • sh is a recipe factory for generating shell-based file recipes.
  • CC, CFLAGS, and LDFLAGS are defined as environment variables through sh.env. sh.env extends the environment of the sh recipe factory with additional variables that are interpolated into the command string and added to the environment of commands run with this factory. In addition to OS environment variables which are added automatically as strings, lists or tuples can be specified in sh.env which will be interpolated correctly into command format strings.
  • compile is defined. It is a normal function which calls the sh factory to generate a recipe for creating an .o output file for the given source file. compile is referred to as a "recipe function", because it is a function that generates a recipe from arguments. Calling this function itself does not run any commands, but instead the recipe generated should be returned from a build target, where it can be built in parallel with other dependencies in the overall dependency tree. The input and output parameters to sh are special and essential:
    • output specifies the name of the file that will be generated by the shell recipe. This is used to determine if the recipe actually needs to be run, and identifies the file that should be cleaned up while cleaning.
    • input is optional, and specifies the file(s) that will be used to create the output. If the output already exists but any of the input files are newer, the output will be re-created.
  • link is defined as another recipe function for creating the final executable from a list of object files.
  • The ntetris2 class is defined. This is the "build class" and defines the targets to be built. The @build decorator is required, and is the catalyst which starts the build process and makes the targets available for building. A build script should define only one build class, as control is given over to Panifex once the class decorator is called.
  • sources is the first target. This target doesn't actually generate any files, rather it defines the list of source files to be built. Since the result of the target isn't a recipe, the source files won't be affected by cleaning or building. This doesn't actually need to be a target, as the list of files to be compiled could be specified outside the build class, but it is made a target to illustrate the previous points.
  • objects is the next target. It depends on sources because it has a parameter named sources which is automatically injected with the result from sources, that being a list of source filenames. It uses compile to create a list of recipes and returns them. Panifex will build these recipes in parallel, spawning at maximum as many simultaneous processes as the system has available processor cores.
  • executable is the final target. It depends on objects, and as such won't actually run until all of the object file recipes generated by objects are done building. executable doesn't receive the list of object recipes, rather it receives a list containing all of the outputs specified by each recipe, that being a list of object filenames.

Release Notes

v1.0: 07/10/2020

  • BACKWARDS INCOMPATIBLE CHANGE: End support for class based build modules.

v0.8: 07/04/2020

  • Updated to support Xeno's new function providers, builds no longer have to be modeled as classes, but build() must be called at the end of the script.

v0.1: 01/02/2020

  • Initial release.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

panifex-1.0.tar.gz (16.7 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page