Build Manifests and Makefiles

generate --makefile writes generated wrapper sources and build instructions. Running the resulting Makefile performs the compilation and linking.

What it writes depends on the input:

Input Generated build files
Fortran or C source Wrapper sources and Makefile.prik
Semantic .pyi contract Wrapper sources, prik-build.json, then Makefile.prik

With a semantic .pyi contract, PRIK first writes prik-build.json and then generates Makefile.prik from that recorded build. With native source input, PRIK generates Makefile.prik directly from the current planned build.

Generate both files from a semantic contract

For a Fortran-native contract:

python3 -m prik generate --makefile contracts/module.pyi \
  --native-fortran-sources native/module.f90 \
  --out-dir build/module

For a C-native contract, select C and provide the C implementation instead:

python3 -m prik generate --makefile --language c contracts/module.pyi \
  --native-c-sources native/module.c \
  --out-dir build/module

Both commands produce this general layout:

build/module/
├── prik-build.json
├── Makefile.prik
├── module_wrapper.c
└── other generated bridge or support sources, when required

Generated source names depend on the contract and selected wrapper route. The --json CLI option selects JSON for PRIK's terminal report; the input mode shown in the table above determines which build files are written.

prik-build.json

prik-build.json is the complete replay contract for one semantic .pyi wrapper build. It records the contract graph, generated sources, native inputs, compiler configuration, compilation units, ordered link inputs, and output extension. Treat it as a generated replay contract and select build settings through the CLI or Python API.

A representative manifest has this structure:

{
  "build_kind": "pyi-wrapper",
  "compiler": {
    "c_flags": [],
    "fortran_flags": [],
    "input_c_executable": "gcc",
    "input_executable": "gfortran",
    "position_independent_code": true,
    "vendor": "GNU",
    "wrapper_c_flags": [],
    "wrapper_compiler_debug": false,
    "wrapper_fortran_flags": []
  },
  "contract_paths": [
    "../../contracts/module.pyi"
  ],
  "entry_contract": "../../contracts/module.pyi",
  "extension": {
    "collision_adapter_all": false,
    "collision_adapters": [],
    "module_name": "module",
    "native_language": "fortran",
    "positional_only": false,
    "requested_name": null
  },
  "generated_wrapper": {
    "native_code_groups": [],
    "sources": [
      "module_wrapper.c"
    ]
  },
  "native_array_build_requirements": {
    "headers": [],
    "items": [],
    "pointer_c_descriptor_interop": false
  },
  "native_build_plan": {
    "compilation_units": [
      {
        "flags": [],
        "include_dirs": [],
        "language": "fortran",
        "module_dir": ".",
        "object": "module.o",
        "source": "../../native/module.f90"
      }
    ],
    "include_dirs": [],
    "library_dirs": [],
    "link_items": [
      {
        "kind": "object",
        "path": "module.o"
      }
    ],
    "module_dirs": [
      "."
    ],
    "prebuilt_artifacts": [],
    "produced_objects": [
      "module.o"
    ]
  },
  "output": {
    "output_dir": ".",
    "shared_library": "module.cpython-<platform>.so",
    "strict_wrapper_names": false
  },
  "schema_version": 4
}

The values and array contents vary by build. In particular, generated_wrapper.native_code_groups records any generated Fortran adapters or support sources, while native_build_plan.link_items preserves the exact order of objects, archives, shared libraries, named libraries, and linker arguments. Paths are stored relative to the manifest directory when possible and resolved from that directory during replay.

Replay reads the current schema version, 4. Regenerate the manifest with the current PRIK version when upgrading from an older schema.

Makefile.prik

Makefile.prik contains the compile and link commands PRIK planned for the wrapper. It is generated for both source and semantic .pyi inputs. Running the Makefile executes those commands.

The file has this general structure; paths, flags, dependencies, and repeated compile rules are shortened here:

# Generated by prik. Edit variables or override them on the make command line.

FC := gfortran
CC := gcc
PRIK_LD := gfortran
PRIK_FFLAGS ?=
PRIK_CFLAGS ?=
PRIK_LDFLAGS ?=

.PHONY: all rebuild clean
all: build/module/module.cpython-<platform>.so

build/module/module.o: native/module.f90
    cd <working-directory> && $(FC) -c ... $(PRIK_FFLAGS) -o module.o

build/module/module_wrapper.o: build/module/module_wrapper.c
    cd <working-directory> && $(CC) -c ... $(PRIK_CFLAGS) -o module_wrapper.o

build/module/module.cpython-<platform>.so: \
    build/module/module.o \
    build/module/module_wrapper.o \
    build/module/prik-build.json \
    contracts/module.pyi
    cd <working-directory> && $(PRIK_LD) -shared ... $(PRIK_LDFLAGS) -o module.cpython-<platform>.so

rebuild:
    $(MAKE) -f build/module/Makefile.prik clean
    $(MAKE) -f build/module/Makefile.prik all

clean:
    rm -f <generated-objects> <shared-library>

The actual file contains complete recorded commands and dependency-safe native source ordering. Generated bridge and binding objects that are independent may still compile in parallel with make -j. For semantic .pyi builds, the link target depends on prik-build.json, the complete .pyi graph, and native link inputs. Source-driven Makefiles instead record the selected source inputs and generated wrapper artifacts directly.

The compiler variables preserve PRIK's selected compilers. The empty PRIK_FFLAGS, PRIK_CFLAGS, and PRIK_LDFLAGS variables let you add flags without replacing the recorded ones:

make -f build/module/Makefile.prik -j4 PRIK_FFLAGS=-O3

Treat the Makefile as generated output. Regenerate it after changing source inputs, semantic contracts, native artifacts, compiler flags, output names, or the PRIK version.

Build or replay

Run the generated Makefile directly:

make -f build/module/Makefile.prik -j4

Use a saved manifest as the complete input for a direct build:

python3 -m prik --build-manifest build/module/prik-build.json

Generate a fresh Makefile.prik from the saved manifest with:

python3 -m prik generate --makefile \
  --build-manifest build/module/prik-build.json

During replay, the saved manifest is authoritative for the output directory, language, wrapper behavior, native inputs, compiler recipe, and ordered link plan. Rerun the original semantic .pyi generate --makefile command to record changes to those inputs.

Evidence

Manifest and Makefile replay behavior is covered by test_pyi_build_modes.py, and source-driven Makefile behavior by test_source_build_modes.py.