cake3 0.3.0.0 → 0.3.0.1
raw patch · 3 files changed
+292/−10 lines, 3 files
Files
- CHANGELOG +11/−0
- README.md +279/−0
- cake3.cabal +2/−10
+ CHANGELOG view
@@ -0,0 +1,11 @@+Version 0.3+-----------+API changes, improve documentation, improve UrWeb extension++Version 0.2+-----------+Redesign (simplify) monadic interface, add support for prebuild/postbuild actions.++Version 0.1+-----------+Initial release
+ README.md view
@@ -0,0 +1,279 @@+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:++ * Stop overusing Make by writing complex logic in make-language+ * Still have a correct Makefile which could be distributed among the users+ * Take a bit of Haskell practice :)++Installation+------------++From Hackage:+ + $ cabal install cake3+++From the Github:++ 1. Install [Haskell Platform](http://www.haskell.org/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 ++ 3. Build the Makefile with cake3++ $ cake3++ 4. 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+++ * Cakefile\_P is an autogenerated module. It defines `file :: String -> File`+ function plus some others.+ * Main building blocks - `rule` functions - build Makefile rules one-to-one.+ The prerequisites are computed based on it's actions.+ * All actions live in Action monad (`A` Monad). `shell` is the most important+ operation of this monad.+ * Quasy-quotation is used to simplify the shell code. `[cmd|..|]` takes a string+ as an argument. It's syntax includes:+ * $name untiquotes hasell expressions `name` of type File, Variable plus few+ others. They define a prerequisites of a rule+ * @name untiquotes hasell expressions `name` of type File. They define+ rule's targets+ * complex expressions are also supported with $(foo bar) and @(bar baz).+ * $$ and @@ expands to $ and @+ * Rules appears in the Makefile in the reversed order. Normally, you want+ 'all' rule to be at the bottom.+++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++ * *Allows spaces inside the filenames.*+ + Everyone knows that Makefiles don't like spaces in filenames. Cake3+ carefully inserts '\ ' to make make happy.++ * *Rebuilds a rule when variable changes.*+ + Consider following antipattern:++ # You often write rules like this, don't you?+ out : in+ foo $(FLAGS) -o $@ $^++ Unfortunately, changes in FLAGS don't lead to rebuilding of out.+ 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](http://stackoverflow.com/a/17830736/1133157) from StackOverflow to+ detect changes in variables and rebuild targets when nessesary.++ rule $ do+ shell [cmd|foo $(extvar "FLAGS") -o @out $in |]++ will rebuild `out` on FLAGS change+ + * *Supports rules with more than one target.*+ + It is not that simple to write a rule which has more than one target. Really,+ + out1 out2 : in1 in2+ foo in1 in2 -o out1 -o out2++ is not corret. Read this [Automake+ article](http://www.gnu.org/software/automake/manual/html_node/Multiple-Outputs.html#Multiple-Outputs)+ if you are surprised. Thirdcake implements [.INTERMEDIATE+ pattern](http://stackoverflow.com/a/10609434/1133157) to deal with this+ problem so `rule` like this++ rule $ do+ shell [cmd|foo $in1 $in2 -o @out1 -o @out2 |]++ will always notice inputs changes and rebuild both outputs++ * *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.++ * *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 monolitic.++### Limitations++#### Make syntax++ * Make is not able to detect directory content chages. For example, user has+ to rerun the ./Cakegen if they add/remove a source file. I plan to automate+ this kind of checks. so it is on my TODO list.+ * ifdef/endif instructions is not supported generally. User has to move this+ logic in Haskell for now. Also on my TODO list+ * Cake3 doesn't check the contents of Makefile variables. It is user's+ responsibility to keep them safe.+ * Variables as targets is not supported. Implement this logic in Haskell for+ now.++#### General++ * 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.+ * 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+-----------------------------++ 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+ _"." </> path_to_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.+
cake3.cabal view
@@ -2,7 +2,7 @@ -- see http://haskell.org/cabal/users-guide/ name: cake3-version: 0.3.0.0+version: 0.3.0.1 synopsis: Third cake the Makefile EDSL description: Cake3 is a Makefile EDSL written in Haskell. Write your build logic in Haskell, obtain clean and safe Makefile, distribute it to the end-users.@@ -56,21 +56,13 @@ . See the README on the GitHub <https://github.com/grwlf/cake3> for more information. Distribution contains several example projects.- .- /Changes/- .- * 0.1 - Initial release- .- * 0.2 - Redesign (simplify) monadic interface, add support for prebuild/postbuild actions.- .- * 0.3 - API changes, improve documentation, improve UrWeb extension - category: Development build-type: Simple cabal-version: >=1.8 data-dir: src data-files: CakeScript.sh, UrEmbedHelp.txt+Extra-Source-Files: README.md, LICENSE, CHANGELOG library exposed-modules: Development.Cake3