Generate ocamldoc, multiple documentation fixes.
authorRichard W.M. Jones <rjones@redhat.com>
Fri, 20 Sep 2013 14:00:56 +0000 (15:00 +0100)
committerRichard W.M. Jones <rjones@redhat.com>
Fri, 20 Sep 2013 14:00:56 +0000 (15:00 +0100)
.gitignore
Makefile.am
configure.ac
goaljobs.mli
html/.gitignore [new file with mode: 0644]

index 68cd58c..42a7a0b 100644 (file)
@@ -31,3 +31,4 @@ Makefile
 /META
 /missing
 /stamp-h1
 /META
 /missing
 /stamp-h1
+/stamp-ocamldoc
index e752ae5..11d4fbd 100644 (file)
@@ -85,6 +85,34 @@ depend: .depend
 rpm: dist
        rpmbuild -ta $(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz
 
 rpm: dist
        rpmbuild -ta $(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz
 
+if HAVE_OCAMLDOC
+
+# HTML library documentation.
+# XXX The list below probably changes with every ocamldoc version.
+# How can we use a wildcard?
+doc_DATA = \
+       html/Goaljobs.html \
+       html/index_attributes.html \
+       html/index_classes.html \
+       html/index_class_types.html \
+       html/index_exceptions.html \
+       html/index.html \
+       html/index_methods.html \
+       html/index_modules.html \
+       html/index_module_types.html \
+       html/index_types.html \
+       html/index_values.html \
+       html/style.css \
+       html/type_Goaljobs.html
+
+$(doc_DATA): stamp-ocamldoc
+stamp-ocamldoc: goaljobs.mli goaljobs.ml
+       rm -f $@
+       $(OCAMLFIND) ocamldoc -html -d html $(OCAMLCPACKAGES) $^
+       touch $@
+
+endif
+
 # License check.
 licensecheck:
        licensecheck $$(git ls-files)
 # License check.
 licensecheck:
        licensecheck $$(git ls-files)
index 755c339..cdf9cfb 100644 (file)
@@ -94,6 +94,10 @@ if test "x$CURL" = "x"; then
     AC_MSG_ERROR([You must install the 'curl' program])
 fi
 
     AC_MSG_ERROR([You must install the 'curl' program])
 fi
 
+dnl ocamldoc (optional)
+AM_CONDITIONAL([HAVE_OCAMLDOC],
+               [test "x$OCAMLDOC" != "xno"])
+
 dnl Check for POD (for manual pages).
 AC_CHECK_PROG(PERLDOC,perldoc,perldoc)
 if test "x$PERLDOC" = "x"; then
 dnl Check for POD (for manual pages).
 AC_CHECK_PROG(PERLDOC,perldoc,perldoc)
 if test "x$PERLDOC" = "x"; then
index daaf0b2..3d342fa 100644 (file)
 
 (** {1 Goaljobs library of useful helper functions.} *)
 
 
 (** {1 Goaljobs library of useful helper functions.} *)
 
-(** {2 Targets and requires}
+(** {2 Target and require}
 
     These are used to write goals.
 
 
     These are used to write goals.
 
-    Normally you write a goal with one or more [target]s and
+    Normally you write a goal with zero or one [target] and
     zero or more [require]s, as the examples below should make
     clear.
 
     zero or more [require]s, as the examples below should make
     clear.
 
-    In the first example, there are two targets: that [o_file] (object)
-    exists, and that it is newer than [c_file] (source).  The rule
+    In the first example, the target is that the [o_file] (object) exists
+    and is newer than the [c_file] (source).  The goal
     meets that target by running the C compiler ([cc]) which, if it
     succeeds, will ensure that the object file exists and is newer
     than the source file.
     meets that target by running the C compiler ([cc]) which, if it
     succeeds, will ensure that the object file exists and is newer
     than the source file.
         target (more_recent [o_file] [c_file]);
 
         sh "cd $builddir && cc -c %s -o %s" c_file o_file
         target (more_recent [o_file] [c_file]);
 
         sh "cd $builddir && cc -c %s -o %s" c_file o_file
-    }
+    v}
 
 
-    In the second example, the rule requires that several files
-    have been compiled ([require (compiled ...)]
+    In the second example, the goal requires that several files
+    have been compiled ([require (compiled ...)])
     before it can link the final program:
 
     {v
     before it can link the final program:
 
     {v
 
         let object = change_file_extension "o" source in
         sh "cd $builddir && cc %s -o %s" object program
 
         let object = change_file_extension "o" source in
         sh "cd $builddir && cc %s -o %s" object program
-    }
+    v}
 
 *)
 
 val target : bool -> unit
   (** [target] {i condition} defines the target condition that {b will}
 
 *)
 
 val target : bool -> unit
   (** [target] {i condition} defines the target condition that {b will}
-      be met once the current rule has run.
+      be met once the current goal has run.
+
+      You can think of the target as a promise or contract that you
+      make, which is met by running the rest of the goal.
 
       Goaljobs is much more flexible than [make].  In [make] only a
       single type of target is possible.  The following are roughly
 
       Goaljobs is much more flexible than [make].  In [make] only a
       single type of target is possible.  The following are roughly
@@ -67,30 +70,33 @@ val target : bool -> unit
       {v
       foo.o: foo.c
         ...
       {v
       foo.o: foo.c
         ...
+      v}
 
 
+      {v
       let goal compiled () =
         target (more_recent ["foo.o"] ["foo.c"]);
       let goal compiled () =
         target (more_recent ["foo.o"] ["foo.c"]);
-        requires (file_exists "foo.c");
+        require (file_exists "foo.c");
         ...
         ...
-      }
+      v}
+
+      Targets in goaljobs can be any arbitrary expression.  For
+      example, it can access network resources or test URLs.
 
 
-      Targets in goaljobs can be any arbitrary expression, and you
-      can have any number of different targets.
+      Almost every goal should have one target, which should
+      accurately state the outcome once the goal has been run.
 
 
-      Almost every rule should have one or more targets, which should
-      accurately state the outcome once the rule has been run.
+      It is possible to have no target.  This means the goal
+      always runs (like using "force" in make).
 
 
-      If you have more than one [target]s then it's as if they have
-      been ORed together ({b not} ANDed which you might expect).
-      You can make this explicit by using a single target and [&&]
-      or [||] between the expressions.  See also {!target_all}
-      and {!target_exists}.
+      You should not have multiple targets in a single goal.  They
+      won't work the way you expect, and future versions of goaljobs
+      will likely stop you from doing this.
 
 
-      Normally you put the target(s) early on in the rule, before any
+      Normally you put the target(s) early on in the goal, before any
       running code and before any [require]s.  This is not a
       hard-and-fast rule and it is not enforced, but doing it will
       running code and before any [require]s.  This is not a
       hard-and-fast rule and it is not enforced, but doing it will
-      ensure the rule runs most efficiently since if the target is met
-      already then the rest of the rule doesn't run. *)
+      ensure the goal runs most efficiently since if the target is met
+      already then the rest of the goal doesn't run. *)
 
 val target_all : bool list -> unit
   (** [target_all [t1; t2; ...]] is the same as writing
 
 val target_all : bool list -> unit
   (** [target_all [t1; t2; ...]] is the same as writing
@@ -101,20 +107,25 @@ val target_exists : bool list -> unit
       [target (t1 || t2 || ...)] *)
 
 val require : (unit -> unit) -> unit
       [target (t1 || t2 || ...)] *)
 
 val require : (unit -> unit) -> unit
-  (** [require] {!goal} defines the requirements of this rule, that
-      is, other goals that have to be met before this rule is able to run.
+  (** [require] {i goal} defines the requirements of this goal, that
+      is, other goals that have to be met before the rest of the
+      goal is able to run.
 
       In terms of [make], [require]s are roughly equivalent to the
       right hand side after the [:], but in goaljobs the requirements
       can be much richer than simply "that file must exist".
 
 
       In terms of [make], [require]s are roughly equivalent to the
       right hand side after the [:], but in goaljobs the requirements
       can be much richer than simply "that file must exist".
 
-      Some very simple rules don't need any [require]s.  Unlike with [make],
-      the requirements of a rule can be placed anywhere within the
-      rule, as long as you put them before they are needed. *)
+      Some very simple goals don't need any [require]s.  You can
+      have as many [require]s as you need in a goal, and you can
+      use a loop or make them conditional if you want.
+
+      Unlike [make], the requirements of a goal can be
+      placed anywhere within the goal, as long as you put them
+      before they are needed. *)
 
 (** {2 Periodic jobs}
 
 
 (** {2 Periodic jobs}
 
-    If you want to have a rule that runs when some outside event
+    If you want to have a goal that runs when some outside event
     happens you have three choices: Manually run the script (this is
     basically what [make] forces you to do).  Have some sort of hook
     that runs the script (eg. a git hook).  Or use a periodic job to
     happens you have three choices: Manually run the script (this is
     basically what [make] forces you to do).  Have some sort of hook
     that runs the script (eg. a git hook).  Or use a periodic job to
@@ -131,16 +142,16 @@ val require : (unit -> unit) -> unit
     let repo = Sys.getenv "HOME" // "repo"
 
     let goal git_commit_tested commit =
     let repo = Sys.getenv "HOME" // "repo"
 
     let goal git_commit_tested commit =
-    let key = sprintf "repo-tested-%s" commit in
-    target (memory_exists key);
+        let key = sprintf "repo-tested-%s" commit in
+        target (memory_exists key);
 
 
-    sh "
-    git clone %s test
-    cd test
-    ./configure
-    make
-    make check
-    ";
+        sh "
+            git clone %s test
+            cd test
+            ./configure
+            make
+            make check
+        ";
 
         (* Record that this commit was tested successfully. *)
         memory_set key "1"
 
         (* Record that this commit was tested successfully. *)
         memory_set key "1"
@@ -150,7 +161,7 @@ val require : (unit -> unit) -> unit
         (* Require that this commit has been tested. *)
         require (git_commit_tested commit)
     )
         (* Require that this commit has been tested. *)
         require (git_commit_tested commit)
     )
-    }
+    v}
 
     Some notes about the above example: Firstly only the current HEAD
     commit is required to be tested.  This is because older commits
 
     Some notes about the above example: Firstly only the current HEAD
     commit is required to be tested.  This is because older commits
@@ -197,7 +208,7 @@ val file_exists : string -> bool
   (** Return true if the named file exists.
 
       This function also exists as a goal.  Writing:
   (** Return true if the named file exists.
 
       This function also exists as a goal.  Writing:
-      {v require (file_exists "somefile");}
+      {v require (file_exists "somefile"); v}
       will die unless ["somefile"] exists. *)
 
 val directory_exists : string -> bool
       will die unless ["somefile"] exists. *)
 
 val directory_exists : string -> bool
@@ -215,7 +226,7 @@ val file_newer_than : string -> string -> bool
 val more_recent : string list -> string list -> bool
   (** [more_recent objects sources] expresses the [make] relationship:
 
 val more_recent : string list -> string list -> bool
   (** [more_recent objects sources] expresses the [make] relationship:
 
-      {v object(s) ...: source(s) ...}
+      {v object(s) ...: source(s) ... v}
 
       in a convenient way:
 
 
       in a convenient way:
 
@@ -223,7 +234,7 @@ val more_recent : string list -> string list -> bool
       let goal built objects sources =
         target (more_recent objects sources);
         ... code to rebuild ...
       let goal built objects sources =
         target (more_recent objects sources);
         ... code to rebuild ...
-      }
+      v}
 
       It is roughly equivalent to checking that all the object files
       exist and are newer than all of the source files.
 
       It is roughly equivalent to checking that all the object files
       exist and are newer than all of the source files.
@@ -269,7 +280,7 @@ val quote : string -> string
 
     {v
       sh "rsync foo-%s.tar.gz example.com:/html/" version
 
     {v
       sh "rsync foo-%s.tar.gz example.com:/html/" version
-    }
+    v}
 
     Each invocation of {!sh} (etc) is a single shell (this is slightly
     different from how [make] works).  For example:
 
     Each invocation of {!sh} (etc) is a single shell (this is slightly
     different from how [make] works).  For example:
@@ -347,7 +358,7 @@ val filter_file_extension : string -> string list -> string
       would return [["bar.o"]] (a single element list). *)
 *)
 
       would return [["bar.o"]] (a single element list). *)
 *)
 
-(** {2 Memory (persistent key/value storage)
+(** {2 Memory (persistent key/value storage)}
 
     "The Memory" is key/value storage which persists across goaljobs
     sessions.  It is stored in the file [$HOME/.goaljobs-memory]
 
     "The Memory" is key/value storage which persists across goaljobs
     sessions.  It is stored in the file [$HOME/.goaljobs-memory]
@@ -370,19 +381,18 @@ val filter_file_extension : string -> string list -> string
         ... some work to test version ...
 
         memory_set key "1"
         ... some work to test version ...
 
         memory_set key "1"
-    }
+    v}
 
     Note in that example the value ["1"] is arbitrary.  You just
     want to store {i any} value so that a later call to {!memory_exists}
 
     Note in that example the value ["1"] is arbitrary.  You just
     want to store {i any} value so that a later call to {!memory_exists}
-    will succeed.
-*)
+    will succeed. *)
 
 val memory_exists : string -> bool
   (** [memory_exists key] checks that the named [key] exists in
       the Memory.  It doesn't matter what value it has.
 
       This is also available as a goal, so you can write
 
 val memory_exists : string -> bool
   (** [memory_exists key] checks that the named [key] exists in
       the Memory.  It doesn't matter what value it has.
 
       This is also available as a goal, so you can write
-      [requires (memory_exists key)] *)
+      [require (memory_exists key)] *)
 
 val memory_set : string -> string -> unit
   (** Set [key] to [value] in the Memory. *)
 
 val memory_set : string -> string -> unit
   (** Set [key] to [value] in the Memory. *)
@@ -404,15 +414,15 @@ val memory_delete : string -> unit
 
     {v
     let goal clean () = sh "rm *~"
 
     {v
     let goal clean () = sh "rm *~"
-    }
+    v}
 
     can be used on the command line:
 
 
     can be used on the command line:
 
-    {v ./script clean }
+    {v ./script clean v}
 
     The special goal called [all] (if it exists) is run implicitly
     unless the user specifies another goal.  Unlike [make], there is
 
     The special goal called [all] (if it exists) is run implicitly
     unless the user specifies another goal.  Unlike [make], there is
-    nothing special about the first rule in the file.
+    nothing special about the first goal in the file.
 
     You can also publish goals, especially ones which take a non-zero
     number of parameters, by calling {!publish}.
 
     You can also publish goals, especially ones which take a non-zero
     number of parameters, by calling {!publish}.
@@ -433,11 +443,11 @@ val publish : string -> (string list -> unit) -> unit
           let sources = List.tl args in
           require (compiled program sources)
       )
           let sources = List.tl args in
           require (compiled program sources)
       )
-      }
+      v}
 
       This could be used as follows:
 
 
       This could be used as follows:
 
-      {v ./script compiled program main.c utils.c }
+      {v ./script compiled program main.c utils.c v}
 
       You will notice you have to write a bit of OCaml code to
       map the string arguments from the command line on to the
 
       You will notice you have to write a bit of OCaml code to
       map the string arguments from the command line on to the
diff --git a/html/.gitignore b/html/.gitignore
new file mode 100644 (file)
index 0000000..d0098b4
--- /dev/null
@@ -0,0 +1,2 @@
+*.css
+*.html