The cake3 package

[Tags: bsd3, library, program]

Cake3 is a EDSL for building Makefiles, written in Haskell. With cake3, developer can write their build logic in Haskell, obtain clean and safe Makefile and distribute it among the non-Haskell-aware users. Currenly, GNU Make is the only backend supported.

Example program

 module Cakefile where

 import Development.Cake3
 import Cakefile_P

 cs = map file ["main.c", "second.c"]

 main = writeMake (file "Makefile") $ do
   selfUpdate
   d <- rule $ do
     shell [cmd|gcc -M $cs -MF @(file "depend.mk")|]
   os <- forM cs $ \c -> do
     rule $ do
       shell [cmd| gcc -c $(extvar "CFLAGS") -o @(c.="o") $c |]
   elf <- rule $ do
     shell [cmd| gcc -o @(file "main.elf") $os |]
   rule $ do
     phony "clean"
     unsafeShell [cmd|rm $elf $os $d|]
   rule $ do
     phony "all"
     depend elf
   includeMakefile d

Basic workflow

See the README on the GitHub https://github.com/grwlf/cake3 for more information. Distribution contains several example projects.


[Skip to ReadMe]

Properties

Versions0.1.0.0, 0.2.1.0, 0.3.0.0, 0.3.0.1, 0.4.0.0, 0.5.0.0, 0.5.1.0, 0.5.2.0, 0.6.0
Change logCHANGELOG
Dependenciesattoparsec, base (==4.6.*), bytestring, containers, deepseq, directory, filepath, haskell-src-meta, language-javascript (==0.5.*), mime-types, monadloc, mtl, optparse-applicative, process, syb, system-filepath, template-haskell, text, text-format [details]
LicenseBSD3
AuthorSergey Mironov
Maintainergrrwlf@gmail.com
CategoryDevelopment
Home pagehttps://github.com/grwlf/cake3
Executablesurembed, cake3
UploadedTue Dec 24 11:22:53 UTC 2013 by SergeyMironov
Downloads1325 total (78 in last 30 days)
Votes
0 []
StatusDocs available [build log]
Successful builds reported [all 1 reports]

Modules

[Index]

Downloads

Maintainers' corner

For package maintainers and hackage trustees

Readme for cake3-0.3.0.1

Cake3

Cake3 is a EDSL for building Makefiles, written in Haskell. With cake3, developer can write their build logic in Haskell, obtain clean and safe Makefile and distribute it among the non-Haskell-aware users. Currenly, GNU Make is the only backend supported.

The Goals

Make is a build tool which was created more than 20 yesrs ago. It has a number of versions and dialects. Basic Makefiles are really easy to write and understand. Unfortunately, it is hard to write real-world scale set of rules correctly due to tricky syntax and lots of pitfails. As of today, Make has automatic, declarative and imperative variables, builtin rules, pattern-rules, double-colon rules, C-style ifdefs (which doesn't work well with declarative variables) and lots of other strange things. Nevertheless, it is still widely used as a de-facto standard tool which everyone has access to.

The goals of Cake3 are to help the developer to:

Installation

From Hackage:

$ cabal install cake3

From the Github:

  1. Install Haskell Platform

  2. Install dependencies

    $ cabal install haskell-src-meta monadloc QuasiText
    
  3. Build the thirdcake from Github

    $ git clone http://github.com/grwlf/cake3
    $ cd cake3
    $ cabal configure && cabal install
    

Usage

  1. Create the Cakefile.hs in the root dir of your project

    $ cake3 init

  2. Edit Cakefile.hs, fill it with rules or other logic you need

    $ vim Cakefile.hs

  3. Debug your generator with

    $ cake3 ghci Prelude> :lo Cakefile.hs

  4. Build the Makefile with cake3

    $ cake3

  5. Run GNU make as usual

How does it work

Cake3 allows user to write Cakefile.hs in plain Haskell to define rules, targets and other stuff as usual. After that, cake3 compiles it into ./Cakegen application which builds your Makefile (ghc is required for that). GNU Make knows how to do the rest.

Example

Here is the example of simple Cakefile.hs:

module Cakefile where

import Development.Cake3
import Cakefile_P

main = writeMake "Makefile" $ do

  selfUpdate

  cs <- filterDirectoryContentsRecursive [".c"]

  d <- rule $ do
    shell [cmd|gcc -M $cs -MF @(file "depend.mk")|]

  os <- forM cs $ \c -> do
    rule $ do
      shell [cmd| gcc -c $(extvar "CFLAGS") -o @(c.="o") $c |]

  elf <- rule $ do
    shell [cmd| gcc -o @(file "main.elf") $os |]

  rule $ do
    phony "clean"
    unsafeShell [cmd|rm $elf $os $d|]

  rule $ do
    phony "all"
    depend elf

  includeMakefile d

Features and limitations

Thirdcake follows Autoconf's path in a sence that it builds the program may do some checks and tests and generates the Makefile. In the same time, the idea of this EDSL is to move as much logic as possible in the final Makefile, to drop the cake3 dependency at the build time.

Of cause, it is possible up to some degree. For example, Cake3 doe not provide a way to scan the project tree with Make's wildcards. But it is possible and may be implemented in future.

Still, some common patterns are supported so I hope that users would call resulting Makefiles safe and robust enough for, say, package maintainers.

Features

Limitations

Make syntax

General

Random implementation details

  1. User writes a cakefile (./Cake*.hs) describing the rules. Refer to Example/GHC/Cakefile.hs. Note, that different cakefiles should have different names even if they are in different directories due to GHC import restrictions. This way user can import one cakefile from another, as if they were in the same directory. Actually, cake3 copies all cakefiles into one temporary directory and compiles them there. Note that cake3 calls ghc having several common haskell extentions enabled.

  2. Cake3 copies all Cake*.hs files from your project tree into temporary dir and compiles them with GHC (or calls GHCi). Before that, it creates a ./Cake*P.hs pathfile containing information about paths. The most important is files_ function which translates relative filename into "." </> pathto_subproject </> filename_.

  3. Cake3 uses relative paths only for the final Makefile.

  4. Cake3 uses it's own representation of files (File). Many filepath functions (takeDirectory, takeBaseName, dropExtensions, </>, etc) are defined for them. See System.FilePath.Wrapper.hs. FileLike typeclass makes it possible to use them with plain FilePath as well.