From d663c9b67d675e6d02fe9883b841b8e80ddc10dc Mon Sep 17 00:00:00 2001 From: Avery Pennarun Date: Sat, 24 Nov 2018 14:36:02 -0500 Subject: [PATCH] First cookbook example for the docs: Hello World in C. --- Documentation/GettingStarted.md | 2 +- Documentation/cookbook/hello.md | 146 ++++++++++++++++++++++++ Documentation/cookbook/hello/.gitignore | 3 + Documentation/cookbook/hello/all.do | 1 + Documentation/cookbook/hello/clean.do | 1 + Documentation/cookbook/hello/hello.c | 6 + Documentation/cookbook/hello/hello.do | 16 +++ Documentation/cookbook/hello/test.do | 12 ++ Documentation/fetchcode.js | 25 ++++ mkdocs.yml | 6 +- 10 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 Documentation/cookbook/hello.md create mode 100644 Documentation/cookbook/hello/.gitignore create mode 100644 Documentation/cookbook/hello/all.do create mode 100644 Documentation/cookbook/hello/clean.do create mode 100644 Documentation/cookbook/hello/hello.c create mode 100644 Documentation/cookbook/hello/hello.do create mode 100644 Documentation/cookbook/hello/test.do create mode 100644 Documentation/fetchcode.js diff --git a/Documentation/GettingStarted.md b/Documentation/GettingStarted.md index 3ade7b5..b7eb954 100644 --- a/Documentation/GettingStarted.md +++ b/Documentation/GettingStarted.md @@ -36,7 +36,7 @@ your home directory: ``` -# Distro packages +# Pre-compiled packages ## MacOS diff --git a/Documentation/cookbook/hello.md b/Documentation/cookbook/hello.md new file mode 100644 index 0000000..77a7798 --- /dev/null +++ b/Documentation/cookbook/hello.md @@ -0,0 +1,146 @@ +### Hello! + +Let's start with Hello World: famously, the simplest project that does +anything interesting. We'll write this one in C, but don't worry if +you're not a C programmer! We'll keep this simple. + +To play with the code on your own machine, get the [redo +source code](https://github.com/apenwarr/redo) and look in the +`Documentation/cookbook/hello/` directory. + +### Compiling the code + +First, let's create a source file that we want to compile: +
+ +Now we need a .do file to tell redo how to build it: +
+ +With those files in place, we can compile and run the program: +```shell +$ redo hello +redo hello + +$ ./hello +Hello, world! +``` + +Use the `redo` command to forcibly re-run a specific rule (in this case, the +compile rule). Or, if you only want to recompile `hello` when its input +files (dependencies) have changed, use `redo-ifchange`. +```shell +$ redo hello +redo hello + +# Rebuilds, whether we need it or not +$ redo hello +redo hello + +# Does not rebuild because hello.c is unchanged +$ redo-ifchange hello + +$ touch hello.c + +# Notices the change to hello.c +$ redo-ifchange hello +redo hello +``` + +Usually we'll want to also provide an `all.do` file. `all` is the +default redo target when you don't specify one. +
+ +With that, now we can rebuild our project by just typing `redo`: +```shell +$ rm hello + +# 'redo' runs all.do, which calls into hello.do. +$ redo +redo all +redo hello + +# Notice that this forcibly re-runs the 'all' +# rule, but all.do calls redo-ifchange, not redo, +# so it doesn't forcibly recompile hello itself. +# +# You can use this trick to experiment with one +# step in your build process at a time, without +# having to play tricks to make that step re-run, +# like you might do with make (eg. by deleting or +# touching files). +$ redo +redo all + +$ ./hello +Hello, world! +``` + + +### Debugging your .do scripts + +If you want to see exactly which commands are being run for each step, +you can use redo's `-x` and `-v` options, which work similarly to +`sh -x` and `sh -v`. + +```shell +$ rm hello + +$ redo -x +redo all +* sh -ex all.do all all all.redo2.tmp ++ redo-ifchange hello + +redo hello +* sh -ex hello.do hello hello hello.redo2.tmp ++ redo-ifchange hello.c ++ cc -o hello.redo2.tmp hello.c -Wall +redo hello (done) + +redo all (done) +``` + + +### Running integration tests + +What about tests? We can, of course, compile a C program that has some +unit tests. But since our program isn't very complicated, let's write +a shell "integration test" (also known as a "black box" test) to make +sure it works as expected, without depending on implementation details: +
+ +Even if we rewrote our hello world program in python, javascript, or +ruby, that integration test would still be useful. + + +### Housekeeping + +Traditionally, it's considered polite to include a `clean` rule that +restores your project to pristine status, so people can rebuild from +scratch: +
+ +Some people like to include a `.gitignore` file so that git won't pester +you about files that would be cleaned up by `clean.do` anyway. Let's add +one: +
.gitignore
+hello
+*~
+.*~
+
+ +Congratulations! That's all it takes to make your first redo project. + +Here's what it looks like when we're done: +```shell +$ ls +all.do clean.do hello.c hello.do test.do +``` + +Some people think this looks a little cluttered with .do files. But +notice one very useful feature: you can see, at a glance, exactly which +operations are possible in your project. You can redo all, clean, +hello, or test. Since most people downloading your project will just +want to build it, it's helpful to have the available actions so +prominently displayed. And if they have a problem with one of the +steps, it's very obvious which file contains the script that's causing +the problem. diff --git a/Documentation/cookbook/hello/.gitignore b/Documentation/cookbook/hello/.gitignore new file mode 100644 index 0000000..bfc5376 --- /dev/null +++ b/Documentation/cookbook/hello/.gitignore @@ -0,0 +1,3 @@ +hello +*~ +.*~ diff --git a/Documentation/cookbook/hello/all.do b/Documentation/cookbook/hello/all.do new file mode 100644 index 0000000..29b0c32 --- /dev/null +++ b/Documentation/cookbook/hello/all.do @@ -0,0 +1 @@ +redo-ifchange hello diff --git a/Documentation/cookbook/hello/clean.do b/Documentation/cookbook/hello/clean.do new file mode 100644 index 0000000..78c90c8 --- /dev/null +++ b/Documentation/cookbook/hello/clean.do @@ -0,0 +1 @@ +rm -f hello *~ .*~ diff --git a/Documentation/cookbook/hello/hello.c b/Documentation/cookbook/hello/hello.c new file mode 100644 index 0000000..d6aa786 --- /dev/null +++ b/Documentation/cookbook/hello/hello.c @@ -0,0 +1,6 @@ +#include + +int main() { + printf("Hello, world!\n"); + return 0; +} \ No newline at end of file diff --git a/Documentation/cookbook/hello/hello.do b/Documentation/cookbook/hello/hello.do new file mode 100644 index 0000000..cb63081 --- /dev/null +++ b/Documentation/cookbook/hello/hello.do @@ -0,0 +1,16 @@ +# If hello.c changes, this script needs to be +# re-run. +redo-ifchange hello.c + +# Compile hello.c into the 'hello' binary. +# +# $3 is the redo variable that represents the +# output filename. We want to build a file +# called "hello", but if we write that directly, +# then an interruption could result in a +# partially-written file. Instead, write it to +# $3, and redo will move our output into its +# final location, only if this script completes +# successfully. +# +cc -o $3 hello.c -Wall diff --git a/Documentation/cookbook/hello/test.do b/Documentation/cookbook/hello/test.do new file mode 100644 index 0000000..6c34492 --- /dev/null +++ b/Documentation/cookbook/hello/test.do @@ -0,0 +1,12 @@ +# Make sure everything has been built before we start +redo-ifchange all + +# Ensure that the hello program, when run, says +# hello like we expect. +if ./hello | grep -i 'hello' >/dev/null; then + echo "success" >&2 + exit 0 +else + echo "missing 'hello' message!" >&2 + exit 1 +fi diff --git a/Documentation/fetchcode.js b/Documentation/fetchcode.js new file mode 100644 index 0000000..3786171 --- /dev/null +++ b/Documentation/fetchcode.js @@ -0,0 +1,25 @@ +'use strict'; + +async function fetchCode(e, lang, src) { + const resp = await fetch(src); + const t = await resp.text(); + e.innerHTML = hljs.highlight(lang, t).value; +} + +function fetchAndHighlightAll() { + const el = document.getElementsByTagName('code'); + for (const e of el) { + const src = e.getAttribute('src'); + if (!src) continue; + const lang = e.getAttribute('lang'); + const title = document.createElement('b'); + title.innerText = src; + title.style.textAlign = 'center'; + title.style.display = 'block'; + e.parentElement.insertBefore(title, e); + fetchCode(e, lang, src); + console.log('found', lang, src); + } +} + +setTimeout(fetchAndHighlightAll, 0); diff --git a/mkdocs.yml b/mkdocs.yml index 0623aa4..5817fb3 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,12 +1,16 @@ -site_name: the _redo_ build system +site_name: "redo: a recursive build system" theme: readthedocs docs_dir: Documentation site_dir: website strict: true +extra_javascript: + - fetchcode.js pages: - Introduction: index.md - Getting Started: GettingStarted.md + - Cookbook: + - Hello World: cookbook/hello.md - FAQ: - Basics: FAQBasics.md - Semantics: FAQSemantics.md