OMAKE-RULES(1)                   Build Tools                    OMAKE-RULES(1)



NAME
       omake  is  a flexible build system designed for building a wide variety
       of projects.  This document describes the syntax and semantics of  rule
       definitions,  which  specify commands to build files in a project.  For
       an overview of omake, see the omake(1) man page.


RULES
       Rules are used by OMake to specify how to build files. At its simplest,
       a rule has the following form.

           <target>: <dependencies>
               <commands>


       The  <target> is the name of a file to be built. The <dependencies> are
       a list of files that are needed before the <target> can be  built.  The
       <commands>  are  a  list of indented lines specifying commands to build
       the target. For example, the following rule specifies how to compile  a
       file hello.c.

           hello.o: hello.c
               $(CC) $(CFLAGS) -c -o hello.o hello.c


       This  rule states that the hello.o file depends on the hello.c file. If
       the hello.c file has changed, the command $(CC) $(CFLAGS) -c -o hello.o
       hello.c is to be executed to update the target file hello.o.

       A rule can have an arbitrary number of commands. The individual command
       lines are executed independently by the command shell. The commands  do
       not have to begin with a tab, but they must be indented from the depen-
       dency line.

       In addition to normal variables, the following special variables may be
       used in the body of a rule.


       *      $*: the target name, without a suffix.

       *      $@: the target name.

       *      $^:  a  list  of the sources, in alphabetical order, with dupli-
              cates removed.

       *      $+: all the sources, in the original order.

       *      $<: the first source.

       For example, the above hello.c rule may be simplified as follows.

           hello.o: hello.c
               $(CC) $(CFLAGS) -c -o $@ $<


       Unlike normal values, the variables in a rule body are expanded lazily,
       and  binding  is dynamic. The following function definition illustrates
       some of the issues.

           CLibrary(name, files) =
               OFILES = $(addsuffix .o, $(files))

               $(name).a: $(OFILES)
                   $(AR) cq $@ $(OFILES)


       This function defines a rule to build a program called $(name)  from  a
       list  of  .o  files.  The files in the argument are specified without a
       suffix, so the first line of the function definition defines a variable
       OFILES that adds the .o suffix to each of the file names. The next step
       defines a rule to build a target library $(name).a from  the  $(OFILES)
       files.  The  expression $(AR) is evaluated when the function is called,
       and the value of the variable AR is taken from the caller's scope  (see
       also the section on Scoping).


   IMPLICIT RULES
       Rules  may  also  be  implicit.  That is, the files may be specified by
       wildcard patterns.  The wildcard character is %. For example, the  fol-
       lowing rule specifies a default rule for building .o files.

           %.o: %.c
               $(CC) $(CFLAGS) -c -o $@ $*.c


       This  rule  is  a  template for building an arbitrary .o file from a .c
       file.

       By default, implicit rules are only used for the targets in the current
       directory.  However  subdirectories  included  via  the  .SUBDIRS rules
       inherit all the implicit rules that are in scope (see also the  section
       on Scoping).


   BOUNDED IMPLICIT RULES
       Implicit  rules may specify the set of files they apply to. The follow-
       ing syntax is used.

           <targets>: <pattern>: <dependencies>
               <commands>


       For example, the following rule applies only to the files a.o and  b.o.

          a.o b.o: %.o: %.c
               $(CC) $(CFLAGS) -DSPECIAL -c $*.c



   SECTION
       Frequently, the commands in a rule body are expressions to be evaluated
       by the shell. omake also allows expressions to be  evaluated  by  omake
       itself.

       The syntax of these ``computed rules'' uses the section expression. The
       following rule uses the  omake  IO  functions  to  produce  the  target
       hello.c.

           hello.c:
               section
                   FP = fopen(hello.c, w)
                   fprintln($(FP), $""#include <stdio.h> int main() { printf("Hello world\n"); }"")
                   close($(FP))


       This  example  uses  the  quotation  $""...""  to  quote the text being
       printed. These quotes are not included in the output file.  The  fopen,
       fprintln,  and  close  functions perform file IO as discussed in the IO
       section.

       In addition, commands that are function calls, or special  expressions,
       are interpreted correctly.  Since the fprintln function can take a file
       directly, the above rule can be abbreviated as follows.

           hello.c:
              fprintln($@, $""#include <stdio.h> int main() { printf("Hello world\n"); }"")



   SECTION RULE
       Rules can also be computed using the section rule form,  where  a  rule
       body  is  expected instead of an expression. In the following rule, the
       file a.c is copied onto  the  hello.c  file  if  it  exists,  otherwise
       hello.c is created from the file default.c.

           hello.c:
               section rule
                  if $(target-exists a.c)
                     hello.c: a.c
                        cat a.c > hello.c
                  else
                     hello.c: default.c
                        cp default.c hello.c



SPECIAL DEPENDENCIES
   :EXISTS:
       In some cases, the contents of a dependency do not matter, only whether
       the file exists or not. In this case, the  :exists:  qualifier  can  be
       used for the dependency.

           foo.c: a.c :exists: .flag
              if $(test -e .flag)
                  $(CP) a.c $@



   :EFFECTS:
       Some  commands  produce files by side-effect. For example, the latex(1)
       command produces a .aux file as a side-effect of producing a .dvi file.
       In  this  case,  the  :effects:  qualifier  can  be  used  to  list the
       side-effect explicitly.  omake is careful to avoid simultaneously  run-
       ning programs that have overlapping side-effects.

           paper.dvi: paper.tex :effects: paper.aux
               latex paper



   :VALUE:
       The  :value:  dependency  is  used  to  specify that the rule execution
       depends on the value of an expression. For example, the following rule

           a: b c :value: $(X)
               ...


       specifies that ``a'' should be recompiled if the value of $(X)  changes
       (X  does  not have to be a filename). This is intended to allow greater
       control over dependencies.

       In addition, it can be used instead of other kinds of dependencies. For
       example, the following rule:

           a: b :exists: c
               commands


       is the same as

           a: b :value: $(target-exists c)
               commands


       Notes:

       *      The values are arbitrary (they are not limited to variables)

       *      The  values are evaluated at rule expansion time, so expressions
              containing variables like $@, $^, etc are legal.


.SCANNER RULES
       Scanner rules define a way to specify automatic dependency scanning.  A
       .SCANNER rule has the following form.

           .SCANNER: target: dependencies
               commands


       The  rule  is  used  to  compute  additional dependencies that might be
       defined in the source files for the specified target. The scanner  pro-
       duces dependencies for the specified target (which may be a pattern) by
       running the commands, which must produce output that is compatible with
       omake.   For  example, on GNU systems the gcc -MM foo.c produces depen-
       dencies for the file foo.c (based on #include information).

       We can use this to specify a scanner for C files that adds the  scanned
       dependencies  for  the  .o  file.  The following scanner specifies that
       dependencies for a file, say foo.o can be computed by running  gcc  -MM
       foo.c.  Furthermore,  foo.c  is  a dependency, so the scanner should be
       recomputed whenever the foo.c file changes.

           .SCANNER: %.o: %.c
               gcc -MM $<


       Let's suppose that the command gcc -MM foo.c prints the following line.

           foo.o: foo.h /usr/include/stdio.h


       The result is that the files foo.h and /usr/include/stdio.h are consid-
       ered to be dependencies of foo.o---that is, foo.o should be rebuilt  if
       either of these files changes.

       This  works, to an extent. One nice feature is that the scanner will be
       re-run whenever the foo.c file changes. However, one  problem  is  that
       dependencies  in  C are recursive.  That is, if the file foo.h is modi-
       fied, it might include other files, establishing further  dependencies.
       What we need is to re-run the scanner if foo.h changes too.

       We  can  do this with a value dependency. The variable $& is defined as
       the dependency results from any previous scan.  We  can  add  these  as
       dependencies using the digest function, which computes an MD5 digest of
       the files.

           .SCANNER: %.o: %.c :value: $(digest $&)
               gcc -MM $<


       Now, when the file foo.h changes, its digest will also change, and  the
       scanner  will  be re-run because of the value dependency (since $& will
       include foo.h).

       This still is not quite right. The problem is that the C compiler  uses
       a  search-path  for include files. There may be several versions of the
       file foo.h, and the one that is chosen depends  on  the  include  path.
       What we need is to base the dependencies on the search path.

       The  $(digest-in-path-optional  ...) function computes the digest based
       on a search path, giving us a solution that works.

           .SCANNER: %.o: %.c :value: $(digest-in-path-optional $(INCLUDES), $&)
              gcc -MM $(addprefix -I, $(INCLUDES)) $<



   NAMED SCANNERS, AND THE :SCANNER: TARGET
       Sometimes it may be useful to specify explicitly which  scanner  should
       be  used in a rule. For example, we might compile .c files with differ-
       ent options, or (heaven help us) we may  be  using  both  gcc  and  the
       Microsoft  Visual C++ compiler cl. In general, the target of a .SCANNER
       is not tied to a particular target, and we may name it as we like.

           .SCANNER: scan-gcc-%.c: %.c :value: $(digest-in-path-optional $(INCLUDES), $&)
               gcc -MM $(addprefix -I, $(INCLUDES)) $<

           .SCANNER: scan-cl-%.c: %.c :value: $(digest-in-path-optional $(INCLUDES), $&)
               cl --scan-dependencies-or-something $(addprefix /I, $(INCLUDES)) $<


       The next step is to define explicit scanner dependencies. The :scanner:
       dependency is used for this. In this case, the scanner dependencies are
       specified explicitly.

           $(GCC_FILES): %.o: %.c :scanner: scan-gcc-%c
               gcc ...

           $(CL_FILES): %.obj: %.c :scanner: scan-cl-%c
               cl ...


       Explicit :scanner: scanner specification may also be used to state that
       a single .SCANNER rule should be used to generate dependencies for more
       than one target. For example,

           .SCANNER: scan-all-c: $(GCC_FILES) :value: $(digest-in-path-optional $(INCLUDES), $&)
               gcc -MM $(addprefix -I, $(INCLUDES)) $(GCC_FILES)

           $(GCC_FILES): %.o: %.c :scanner: scan-all-c
               ...


       The above has the advantage of only running gcc once and a disadvantage
       that when a single source file changes, all the files will end up being
       re-scanned.


   NOTES
       In most cases, you won't need to define scanners of your own. The stan-
       dard  installation  includes  default  scanners  (both  explicitly  and
       implicitly named ones) for C, OCaml, and LaTeX files.

       The SCANNER_MODE variable controls the usage of implicit scanner depen-
       dencies.  See  the  documentation  for  the  SCANNER_MODE  variable  in
       omake-root(1) for detail.

       The explicit :scanner:  dependencies  reduce  the  chances  of  scanner
       mis-specifications.  In  large  complicated projects it might be a good
       idea to set SCANNER_MODE to error and use only the named .SCANNER rules
       and explicit :scanner: specifications.


OTHER SPECIAL TARGETS
       There  are several other special targets that define special actions to
       be take by omake.


   .DEFAULT
       The .DEFAULT target specifies a target to be built by default if  omake
       is  run without explicit targets. The following rule instructs omake to
       build the program hello by default

          .DEFAULT: hello



   .SUBDIRS
       The .SUBDIRS target is used to specify a set of subdirectories that are
       part  of  the project. Each subdirectory should have its own OMakefile,
       which is evaluated in the context of the current environment.

          .SUBDIRS: src doc tests


       This rule specifies that the OMakefiles in each of the  src,  doc,  and
       tests directories should be read.

       In  some  cases,  especially  when the OMakefiles are very similar in a
       large number of subdirectories, it is inconvenient to have  a  separate
       OMakefile for each directory. If the .SUBDIRS rule has a body, the body
       is used instead of the OMakefile.

          .SUBDIRS: src1 src2 src3
             println(Subdirectory $(CWD))
             .DEFAULT: lib.a


       In this case, the src1, src2, and src3 files do  not  need  OMakefiles.
       Furthermore,  if  one exists, it is ignored. The following includes the
       file if it exists.

          .SUBDIRS: src1 src2 src3
              if $(file-exists OMakefile)
                 include OMakefile
              .DEFAULT: lib.a



   .INCLUDE
       The .INCLUDE target is like the include directive, but it  specifies  a
       rule to build the file if it does not exist.

          .INCLUDE: config
              echo "CONFIG_READ = true" > config

           echo CONFIG_READ is $(CONFIG_READ)



   .PHONY
       A  ``phony''  target is a target that is not a real file, but exists to
       collect a set of dependencies.  Phony targets are  specified  with  the
       .PHONY rule. In the following example, the install target does not cor-
       respond to a file, but it corresponds to some commands that  should  be
       run whenever the install target is built (for example, by running omake
       install).

          .PHONY: install

          install: myprogram.exe
             cp myprogram.exe /usr/bin



RULE SCOPING
       As we have mentioned before, omake is a scoped language. This  provides
       great flexibility---different parts of the project can define different
       configurations without interfering with one another (for  example,  one
       part  of the project might be compiled with CFLAGS=-O3 and another with
       CFLAGS=-g).

       But how is the scope for a target file selected? Suppose we are  build-
       ing  a file dir/foo.o.  omake uses the following rules to determine the
       scope.


       *      First, if there is an explicit rule for  building  dir/foo.o  (a
              rule  with  no  wildcards), the context for that rule determines
              the scope for building the target.

       *      Otherwise, the directory dir/ must be part of the project.  This
              normally  means  that  a configuration file dir/OMakefile exists
              (although, see the .SUBDIRS section for another way  to  specify
              the  OMakefile).  In  this  case, the scope of the target is the
              scope at the end of the dir/OMakefile.

       To illustrate rule scoping, let's go back to the example of  a  ``Hello
       world''  program  with two files. Here is an example OMakefile (the two
       definitions of CFLAGS are for illustration).

           # The executable is compiled with debugging
           CFLAGS = -g
           hello: hello_code.o hello_lib.o
              $(CC) $(CFLAGS) -o $@ $+

           # Redefine CFLAGS
           CFLAGS += -O3


       In this project, the target hello is explicit.  The scope of the  hello
       target  is the line beginning with hello:, where the value of CFLAGS is
       -g. The other two targets, hello_code.o and hello_lib.o do  not  appear
       as  explicit  targets,  so  their scope is at the end of the OMakefile,
       where the CFLAGS variable is defined to be -g -O3. That is, hello  will
       be  linked  with  CFLAGS=-g  and  the  .o  files  will be compiled with
       CFLAGS=-g -O3.

       We can change this behavior for any of the targets by  specifying  them
       as   explicit   targets.  For  example,  suppose  we  wish  to  compile
       hello_lib.o with a preprocessor variable LIBRARY.

           # The executable is compiled with debugging
           CFLAGS = -g
           hello: hello_code.o hello_lib.o
              $(CC) $(CFLAGS) -o $@ $+

           # Compile hello_lib.o with CFLAGS = -g -DLIBRARY
           section
               CFLAGS += -DLIBRARY
               hello_lib.o:

           # Redefine CFLAGS
           CFLAGS += -O3


       In this case, hello_lib.o is also mentioned as an explicit target, in a
       scope where CFLAGS=-g -DLIBRARY. Since no rule body is specified, it is
       compiled using the usual implicit rule for building .o files (in a con-
       text where CFLAGS=-g -DLIBRARY).


   SCOPING OF IMPLICIT RULES
       Implicit  rules  (rules  containing  wildcard patterns) are not global,
       they follow the normal scoping convention. This allows different  parts
       of  a  project to have different sets of implicit rules. If we like, we
       can modify the example above to provide a new implicit rule for  build-
       ing hello_lib.o.

           # The executable is compiled with debugging
           CFLAGS = -g
           hello: hello_code.o hello_lib.o
              $(CC) $(CFLAGS) -o $@ $+

           # Compile hello_lib.o with CFLAGS = -g -DLIBRARY
           section
               %.o: %.c
                   $(CC) $(CFLAGS) -DLIBRARY -c $<
               hello_lib.o:

           # Redefine CFLAGS
           CFLAGS += -O3


       In  this  case,  the  target hello_lib.o is built in a scope with a new
       implicit rule for building %.o files. The implicit rule adds the  -DLI-
       BRARY  option.  This  implicit  rule  is  defined  only  for the target
       hello_lib.o; the target hello_code.o is built as normal.


   SCOPING OF .SCANNER RULES
       Scanner rules are scoped the same way as normal rules. If the  .SCANNER
       rule  is  explicit (containing no wildcard patterns), then the scope of
       the scan target is the same as the the rule.  If the .SCANNER  rule  is
       implicit,  then the environment is taken from the :scanner: dependency.

           # The executable is compiled with debugging
           CFLAGS = -g
           hello: hello_code.o hello_lib.o
              $(CC) $(CFLAGS) -o $@ $+

           # scanner for .c files
           .SCANNER: scan-c-%.c: %.c
              $(CC) $(CFLAGS) -MM $<

           # Compile hello_lib.o with CFLAGS = -g -DLIBRARY
           section
               CFLAGS += -DLIBRARY
               hello_lib.o: hello_lib.c :scanner: scan-c-hello_lib.c
                  $(CC) $(CFLAGS) -c $<

           # Compile hello_code.c with CFLAGS = -g -O3
           section
               CFLAGS += -O3
               hello_code.o: hello_code.c :scanner: scan-c-hello_code.c
                  $(CC) $(CFLAGS) -c $<


       Again, this is for illustration---it is  unlikely  you  would  need  to
       write a complicated configuration like this! In this case, the .SCANNER
       rule specifies that the C-compiler should be called with the  -MM  flag
       to  compute  dependencies.  For  the target hello_lib.o, the scanner is
       called with CFLAGS=-g -DLIBRARY, and for hello_code.o it is called with
       CFLAGS=-g -O3.


   SCOPING FOR .PHONY TARGETS
       Phony  targets  (targets  that  do not correspond to files) are defined
       with a .PHONY: rule.  Phony targets are scoped as usual. The  following
       illustrates a common mistake, where the .PHONY target is declared after
       it is used.

           # This example is broken!
           all: hello

           hello: hello_code.o hello_lib.o
               $(CC) $(CFLAGS) -o $@ $+

           .PHONY: all


       This doesn't work as expected because the .PHONY declaration occurs too
       late.  The proper way to write this example is to place the .PHONY dec-
       laration first.

           # Phony targets must be declared before being used
           .PHONY: all

           all: hello

           hello: hello_code.o hello_lib.o
               $(CC) $(CFLAGS) -o $@ $+


       Phony targets are passed to subdirectories. As a practical  matter,  it
       is  wise  to  declare all .PHONY targets in your root OMakefile, before
       any .SUBDIRS. This will ensure that 1) they  are  considered  as  phony
       targets  in  each  of the sbdirectories, and 2) you can build them from
       the project root.

           .PHONY: all install clean

           .SUBDIRS: src lib clib



REFERENCES
   SEE ALSO
       omake(1),   omake-quickstart(1),    omake-options(1),    omake-root(1),
       omake-language(1),   omake-shell(1),   omake-rules(1),   omake-base(1),
       omake-system(1), omake-pervasives(1), osh(1), make(1)


   VERSION
       Version: 0.9.6.7 of December 28, 2005.


   LICENSE AND COPYRIGHT
       (C)2003-2005, Jason Hickey, Caltech 256-80, Pasadena, CA 91125, USA

       This program is free software; you can redistribute it and/or modify it
       under  the  terms of the GNU General Public License as published by the
       Free Software Foundation; either version 2 of the License, or (at  your
       option) any later version.

       This  program  is  distributed  in the hope that it will be useful, but
       WITHOUT ANY  WARRANTY;  without  even  the  implied  warranty  of  MER-
       CHANTABILITY  or  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
       Public License for more details.

       You should have received a copy of the GNU General Public License along
       with this program; if not, write to the Free Software Foundation, Inc.,
       675 Mass Ave, Cambridge, MA 02139, USA.


   AUTHOR
       Jason Hickey
       Caltech 256-80
       Pasadena, CA 91125, USA
       Email: jyh@cs.caltech.edu
       WWW: http://www.cs.caltech.edu/~jyh




Build Tools                    December 28, 2005                OMAKE-RULES(1)
