# Changelog for `Cabal-hooks`

## 3.18.1.0 — July 2026

- Stop exposing constructors of `RuleCommands` [#11461](https://github.com/haskell/cabal/issues/11461) [#11771](https://github.com/haskell/cabal/pull/11771)

  The constructors of the `SetupHooks` `RuleCommands` are no longer exposed
  from `Distribution.Simple.SetupHooks`. These were rather gnarly internal
  constructors; the intended public API is via `staticRule` and `dynamicRule`.

- Make Cabal-hooks library more self-sufficient [#11772](https://github.com/haskell/cabal/pull/11772)

  The `Distribution.Simple.SetupHooks` module from `Cabal-hooks` now re-exports
  a lot of the functionality that is commonly needed when writing `SetupHooks`:

    - File-path related functionality from `Distribution.Utils.Path`.
    - Functionality related to the program database: `lookupProgram`, `runProgramCwd`.
    - IO utilities such as `warn`, `createDirectoryIfMissingVerbose`, and `rewriteFileEx`.
    - Various types frequently used in pre-build rules, such as `Binary`,
      `ModuleName`.
    - Functions that extract information from `LocalBuildInfo` such as
      `localPkgDescr`, `mbWorkDirLBI`, `withPrograms`, `interpretSymbolicPathLBI`
      and `componentBuildInfo`.

  In addition, new file monitoring helper functions `findAndMonitorDirFileGlob`
  and `findAndMonitorSourceDirsFileExts` have been added. These make it very
  simple and convenient to search for a file glob or files with a particular
  extension in the source directories, for pre-build rules.

- Recompilation checking for SetupHooks pre-build rules [#11730](https://github.com/haskell/cabal/issues/11730) [#11731](https://github.com/haskell/cabal/pull/11731)

  Pre-build rules are now only re-run when stale, according to the conditions
  described in the [SetupHooks
  API](https://hackage.haskell.org/package/Cabal-hooks/docs/Distribution-Simple-SetupHooks.html).
  That is, a rule is re-run if any of the following conditions are satisfied:

    - The rule is new, or
    - A dependency of the rule is stale.
      That is, either we have re-run another rule that this rule depends on,
      or one of the file inputs to the rule is newer than the oldest output of the
      rule (or the rule output doesn't exist at all), or
    - The rule itself has changed, e.g. the parameters stored in `RuleData`
      have changed.

  In particular, Cabal will now write per-component caches of pre-build rules
  in order to compute which rules have changed between runs, with file name
  "setup-hooks-rules.cache".

- Pre-build rules can generate extra sources and bundled libraries [#10791](https://github.com/haskell/cabal/issues/10791) [#11607](https://github.com/haskell/cabal/issues/11607) [#11573](https://github.com/haskell/cabal/pull/11573)

  It is now possible to write pre-build rules that generate source files other
  than Haskell files, as well as extra bundled library files.

  Because there is no counterpart to `autogen-modules` for non-Haskell source
  files, you will need to proceed in two steps:

    1. In a per-component pre-configure hook, add the files you want to generate
       to the relevant fields, e.g. the `cSources` field of `BuildInfo` for a
       C source file.

       These files must be relative to `autogenCompModulesDir`.

    2. Pre-build rules generating these files will now be demanded. This avoids
       getting an error message "The following pre-build rules are not demanded
       and will not be run".

  Note that include files (such as `.h` files) are a bit different: any files
  listed under `includes`/`autogen-includes` are required at **configure**
  time.  This gives `SetupHooks` authors two choices: either list the include
  files in `autogen-includes` but generate them in a pre-configure hook, or
  don't list them there and generate them in a pre-build rule, relying on the
  files getting picked up from included directories (this may be brittle).

- Fixed binary format mismatch resulting in `runRuleDynDepsCmd` build error [#12053](https://github.com/haskell/cabal/issues/12053) [#12054](https://github.com/haskell/cabal/pull/12054)


    A build containing a `dynamicRule` would fail with the following error:

    ```
    Error: [Cabal-7125]
    Failed to build hooks-0.1.0.0. The exception was:
    Missing ByteString argument in 'ruleExecCmd'.
    Run 'runRuleDynDepsCmd' on the rule to obtain this data.
    ```

    This was caused by a mismatch between the binary formats used to encode
    and decode the rules.  The hook produced a result of type `([Dependency],
    LBS.ByteString)`, which was then encoded into a `Binary` blob.  However,
    `hooks-exe` decoded this data as `Maybe ([Dependency], LBS.ByteString)`,
    causing the build error.

## 3.16.1 – December 2025
  * No changes

## 3.16.0 – July 2025
  * No changes

## 3.14.2 – April 2025
  * No changes

## 3.14 – November 2024

  * Initial release of the `Hooks` API.
