@@ -44,7 +44,7 @@ currently four snapshot types:
4444* No snapshot, just use packages shipped with the compiler. For GHC this looks
4545 like ` snapshot: ghc-9.6.5 `
4646* Custom snapshot, via a URL or relative file path. For further information, see
47- the [ snapshot and package location] ( ../../topics/pantry .md ) documentation.
47+ the [ snapshot location] ( ../../topics/snapshot_location .md ) documentation.
4848
4949Each of these snapshots will also determine what constraints are placed on the
5050compiler version. See the [ compiler-check] ( non-project.md#compiler-check ) option
@@ -122,7 +122,8 @@ A Pantry package location is one or three different kinds of sources:
122122* a Git or Mercurial repository.
123123
124124For further information on the format for specifying a Pantry package location,
125- see the [Pantry](../../topics/pantry.md) documentation. For example :
125+ see the [package location](../../topics/package_location.md) documentation. For
126+ example :
126127
127128~~~yaml
128129extra-deps :
@@ -314,7 +315,95 @@ custom-preprocessor-extensions:
314315- erb
315316~~~
316317
317- TODO : Add a simple example of how to use custom preprocessors.
318+ ??? example "Use of a custom preprocessor"
319+
320+ The [Ruby](https://www.ruby-lang.org/en/) programming language provides
321+ [`erb`](https://docs.ruby-lang.org/en/master/ERB.html) at the command line.
322+ ` erb` provides a templating system for Ruby. The following example uses
323+ ` erb` as a custom preprocessor.
324+
325+ The example is a single-package project with a customised `Setup.hs`, which
326+ Stack will use to build :
327+ ~~~haskell
328+ {-# LANGUAGE CPP # -}
329+
330+ module Main
331+ ( main
332+ ) where
333+
334+ import Distribution.Simple ( defaultMainWithHooks, simpleUserHooks )
335+ import Distribution.Simple.PreProcess
336+ ( PreProcessor (..), mkSimplePreProcessor, unsorted )
337+ import Distribution.Simple.UserHooks ( UserHooks (..) )
338+ import Distribution.Types.BuildInfo ( BuildInfo )
339+ import Distribution.Types.ComponentLocalBuildInfo
340+ ( ComponentLocalBuildInfo )
341+ import Distribution.Types.LocalBuildInfo ( LocalBuildInfo )
342+ import System.Process ( readCreateProcess, proc, shell )
343+
344+ main : : IO ()
345+ main = defaultMainWithHooks simpleUserHooks
346+ { hookedPreProcessors = [("erb", runRuby)]
347+ }
348+
349+ runRuby : :
350+ BuildInfo
351+ -> LocalBuildInfo
352+ -> ComponentLocalBuildInfo
353+ -> PreProcessor
354+ runRuby _ _ _ = PreProcessor
355+ { platformIndependent = True
356+ , ppOrdering = unsorted
357+ , runPreProcessor = mkSimplePreProcessor $ \erbFile fout verbosity ->
358+ readCreateProcess (erbProcess erbFile) "" >>= writeFile fout
359+ }
360+ where
361+ erbProcess erbFile =
362+ # if defined(mingw32_HOST_OS)
363+ shell $ "erb " <> erbFile
364+ # else
365+ proc "erb" [erbFile]
366+ # endif
367+ ~~~
368+
369+ The example has a package description file (`package.yaml`) that specifies a
370+ `Custom` build type :
371+ ~~~yaml
372+ spec-version : 0.36.0
373+ name : my-package
374+ version : 0.1.0.0
375+ build-type : Custom
376+
377+ dependencies : base
378+
379+ custom-setup :
380+ dependencies :
381+ - base
382+ - Cabal
383+ - process
384+
385+ library :
386+ source-dirs : src
387+ generated-exposed-modules : MyModule
388+ ~~~
389+
390+ The example has a `src/MyModule.erb` file that will be preprocessed to
391+ create Haskell source code :
392+ ~~~text
393+ module MyModule where
394+
395+ <% (1..5).each do |i| % >
396+ test<%= i %> : : Int
397+ test<%= i %> = <%= i %>
398+ <% end % >
399+ ~~~
400+
401+ The example has a project-level configuration file (`stack.yaml`) :
402+ ~~~yaml
403+ snapshot : lts-22.30
404+ custom-preprocessor-extensions :
405+ - erb
406+ ~~~
318407
319408# # extra-package-dbs
320409
0 commit comments