cake3 alternatives and similar packages
Based on the "Development" category.
Alternatively, view cake3 alternatives based on common mentions on social networks and blogs.
stack10.0 2.7 cake3 VS stackThe Haskell Tool Stack
hadolint10.0 6.0 cake3 VS hadolintDockerfile linter, validate inline bash, written in Haskell
ShellCheck10.0 7.5 cake3 VS ShellCheckShellCheck, a static analysis tool for shell scripts
ihaskell10.0 8.1 cake3 VS ihaskellA Haskell kernel for the Jupyter project.
hlint9.9 8.0 cake3 VS hlintHaskell source code suggestions
haddock9.9 5.8 cake3 VS haddockHaskell Documentation Tool
hie-core9.9 9.9 cake3 VS hie-coreThe Daml smart contract language
ormolu9.9 5.8 cake3 VS ormoluA formatter for Haskell source code
leksah9.9 2.6 cake3 VS leksahHaskell IDE
ghcid9.9 0.0 cake3 VS ghcidVery low feature GHCi based IDE
ghcide9.9 9.0 cake3 VS ghcideA library for building Haskell IDE tooling
niv9.9 0.0 cake3 VS nivEasy dependency management for Nix projects
ghc-mod9.9 0.0 cake3 VS ghc-modHappy Haskell Programming
hoogle9.9 3.8 cake3 VS hoogleHaskell API search engine
shake9.9 0.0 cake3 VS shakeShake build system
haddock-api9.9 5.8 cake3 VS haddock-apiHaskell Documentation Tool
intero9.9 0.4 cake3 VS interoComplete interactive development program for Haskell
ghci-ng9.9 0.4 cake3 VS ghci-ngNext generation GHCi
shelly9.8 2.1 cake3 VS shellyHaskell shell scripting
retrie9.8 0.0 cake3 VS retrieRetrie is a powerful, easy-to-use codemodding tool for Haskell.
stgi9.8 0.0 cake3 VS stgiA user-centric visual STG implementation to help understand GHC/Haskell's execution model.
hpack9.8 0.0 cake3 VS hpackhpack: A modern format for Haskell packages
criterion9.8 4.3 cake3 VS criterionA powerful but simple library for measuring the performance of Haskell code.
hindent9.8 4.8 cake3 VS hindentHaskell pretty printer
stan9.8 3.2 cake3 VS stan🕵️ Haskell STatic ANalyser
structured-haskell-mode9.8 0.0 cake3 VS structured-haskell-modeStructured editing minor mode for Haskell in Emacs
cabal-install-parsers9.8 2.1 cake3 VS cabal-install-parsersScripts and instructions for using CI services (e.g. Travis CI or Appveyor) with multiple GHC configurations
haskell-lsp9.8 4.2 cake3 VS haskell-lspHaskell library for the Microsoft Language Server Protocol
H9.8 0.0 cake3 VS HThe full power of R in Haskell.
inline-c9.7 0.0 cake3 VS inline-cWrite Haskell source files including C code inline. No FFI required.
inline-java9.7 0.0 cake3 VS inline-javaHaskell/Java interop via inline Java code in Haskell modules.
alex9.7 0.0 cake3 VS alexA lexical analyser generator for Haskell
gi-atk9.7 0.0 cake3 VS gi-atkGenerate Haskell bindings for GObject-Introspection capable libraries
elm-make9.7 0.0 cake3 VS elm-makeA build tool for Elm projects
curryrs9.7 0.0 cake3 VS curryrsBridge the gap between Haskell and Rust
nixfmt9.7 0.0 cake3 VS nixfmtA formatter for Nix code
fourmolu9.7 7.6 cake3 VS fourmoluA fourk of ormolu that uses four space indentation and allows arbitrary configuration. Don't like it? PRs welcome!
happy9.7 0.0 cake3 VS happyThe Happy parser generator for Haskell
lambdabot9.6 0.0 cake3 VS lambdabotA friendly IRC bot and apprentice coder, written in Haskell.
lambdabot-core9.6 0.0 cake3 VS lambdabot-coreA friendly IRC bot and apprentice coder, written in Haskell.
scion9.6 0.0 cake3 VS scionOLD, DEPRECATED: Use this instead https://github.com/haskell/haskell-ide-engine
hie-bios9.6 4.5 cake3 VS hie-biosSet up a GHC API session for various Haskell Projects
git-gpush9.6 0.0 cake3 VS git-gpushMore intelligent push-to-GitHub utility.
c2hs9.6 0.0 cake3 VS c2hsc2hs is a pre-processor for Haskell FFI bindings to C libraries
halive9.6 0.0 cake3 VS haliveLive recompiler for Haskell
gtk2hs-buildtools9.6 0.0 cake3 VS gtk2hs-buildtoolsGUI library for Haskell based on GTK+
lit9.6 0.0 cake3 VS litA modern tool for literate programming
uhc-light9.5 0.0 cake3 VS uhc-lightPart of UHC packaged as cabal/hackage installable library
Clean code begins in your IDE with SonarLint
Do you think we are missing an alternative of cake3 or a related project?
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. Currently, GNU Make is the only backend supported.
Make is a build tool which was created more than 20 years 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:
- Stop overusing Make by writing complex logic in make-language
- Still have a correct Makefile which could be distributed among the end-users
- Practice some Haskell
$ cabal install cake3
From the Github:
Install Haskell Platform
$ cabal install haskell-src-meta monadloc QuasiText
Build the thirdcake from Github
$ git clone http://github.com/grwlf/cake3 $ cd cake3 $ cabal configure && cabal install
Create the Cakefile.hs in the root dir of your project
$ cake3 init
Edit Cakefile.hs, fill it with rules or other logic you need
$ vim Cakefile.hs
Debug your generator with
$ cake3 ghci Prelude> :lo Cakefile.hs
Build the Makefile with cake3
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 things as usual.
cake3 executable compiles it into ./Cakegen
application which outputs your Makefile (ghc is required for that). GNU Make
knows how to do the rest.
Here is the example of simple Cakefile.hs:
module Cakefile where import Development.Cake3 import Cakefile_P main = writeMake (file "Makefile") $ do selfUpdate cs <- return $ [file "main.c", file "second.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 "all" depend elf includeMakefile d
- Cakefile_P is an autogenerated module. It defines
file :: String -> Filefunction plus some others.
- Main building blocks -
rulefunctions - build Makefile rules one-to-one. The prerequisites are computed based on it's actions.
- All actions live in Action monad (
shellis the most important operation of this monad.
- Quasy-quotation is used to simplify writing of the shell code.
[cmd|..|]takes a string as an argument. The following antiquotations are supported:
- $name antiquotes Hasell expressions
nameof type File, Variable, few others. The name will be placed to the set of prerequisites of the rule.
- @name antiquotes Hasell expressions
nameof type File. The name will be placed to the set of rule's targets.
- complex Haskell expressions inside antiquotations are supported with $(foo bar) and @(bar baz) syntax.
- $$ and @@ expands to $ and @.
- $name antiquotes Hasell expressions
- Rules appears in the Makefile in the reversed order. Normally, you want 'all' rule to be defined at the bottom of Cakefile.hs.
- Starting from 0.4, cake3 outputs rule named 'clean' automatically. This rule contains recipe which deletes all intermediate files with 'rm' command.
selfUpdatecall includes the self-updating dependencies. That means, that Makefile will depend on Cakefile.hs and thus will require ghc to present in the system. Removing
selfUpdatecall will make the Makefile fully Haskell-independent.
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.
Cake3 generates the 'clean' rule automatically.
But if you define your own 'clean', cake3 will take it as is.
Cake3 takes care of spaces inside the filenames.
Everyone knows that Makefiles don't like spaces in filenames. Cake3 carefully inserts '\ ' to make make happy.
Cake3 rebuilds a rule's target when variable changes.
Consider following antipattern:
# You often write rules like this, don't you? program : program.c gcc $(FLAGS) -o [email protected] $^
Unfortunately, changes in FLAGS don't lead to rebuilding of the program. Hardly-trackable bugs may appear if one part of a project was built with one set of optimisation flags and another part was build with another set by mistake.
Thirdcake implements the makevar checksum pattern from StackOverflow to detect changes in variables and rebuild targets when nessesary.
rule $ do shell [cmd|gcc $(extvar "FLAGS") -o @program $program_c |]
programevery time the FLAGS change
Rules may have more than one target.
It is not that simple to write a rule which has more than one target in Makefile. Indeed,
out1 out2 : in1 in2 foo in1 in2 -o out1 -o out2
is not corret. Read this Automake article if you are surprised. Cake3 implements .INTERMEDIATE pattern to deal with this problem so
rule $ do shell [cmd|foo $in1 $in2 -o @out1 -o @out2 |]
will always notice inputs changes and rebuild both outputs
Cake3 supports global prebuild\postbuild actions
Common human-made Makefile with prebuild commands would support them for one rule, typically, "all". Other targets often stay uncovered. Cake3 makes sure that actions are executed for any target you call.
Cake3 lets user organize build hierarchy.
Say, we have a project A with subproject L. L has it's own Makefile and we want to re-use it from our global A/Makefile. Make provides only two ways of doing that. We could either include L/Makefile or call $(MAKE) -C L. First solution is a pain because merging two Makefiles together is generally a hard work. Second approach is OK, but only if we don't need to pass additional paramters or depend on a specific rule from L.
Thirdcake's approach in this case is a compromise: since it employs Haskell's module system, it is possible to write:
-- Project/lib/CakeLib.hs import CakeLib_P.hs librule = do rule $ do shell [cmd|build a lib|] -- Project/Cakefile.hs import Cakefile_P.hs import CakeLib.hs -- ^ note the absence of lib folder here. cake3 will copy all Cake*hs to -- the temp dir, then build them there. all = do lib <- librule rule $ do shell [cmd|build an app with $lib |]
A/Cakefile.hs and do whatever you want to. Resulting makefiles will always be monolithic.
Cake3 may generate different versions of Makefile at once
We often want to generate developer's and end-user's makefiles. End-user version may want treat several rules as pre-executed. Cake3 easily allows us to do that by using 'slicing' utility. See ./Examples/GCC_SED/Cakefile.hs for details.
As a summary - only a small subset of Make syntax is supported. For complex algorithms Haskell looks more suitable so implement everything you need inside the Cakefile.hs. In particular:
- Cake3 offers no way of detecting directory content chages at the moment. For example, user has to rerun the ./Cakegen if they add/remove a source file.
- Cake3 doesn't check the contents of Makefile variables. It is user's responsibility to keep them safe.
- DSL doesn't allow to place Make variables anywhere except the recipe.
- Resulting Makefile is actually a GNUMakefile. GNU extensions (shell function and others) are needed to make various tricks to work. Also, POSIX environment with coreututils package is required. So, Linux, Probably Mac, Probably Windows+Cygwin are the platforms which run cake3.
- All Cakefiles across the project tree should have unique names in order to be copied. Duplicates are found, the first one is used.
Random implementation details
cake3 script copies all the Cake*hs files it found in the project tree to a single temporary directory before compiling the ./Cakegen application. That is why all the cakefiles in project should have different names. Another consequence - cakefiles as Haskell modules may be imported by filename regardles of their actual position in the project tree.
Cake3 creates ./Cake*_P.hs files for every Cake*hs. The _P files contain paths information. In particular, they define
filefunction for the current directiory.
selfUpdatefunction is also defined there.
All filepaths in the final Makefile are relative.
Cake3 uses it's own representation of files (File). Many filepath functions (takeDirectory, takeBaseName, dropExtensions, </>, etc) are defined for File as members of FileLike typeclass. See System.FilePath.Wrapper for the details.