[Omake] A minimal tag system for omake

Alain Frisch alain.frisch at lexifi.com
Wed Dec 5 05:15:01 PST 2007


Hello,

One thing I've found quite painful with omake is that it is difficult to 
compose the command lines in a modular way for implicit rules. I've 
started to implement a system reminiscent of ocamlbuild's tags, in a 
much more limited way.

The idea is to attach tags to files. Some variables used in command 
lines (like CFLAGS, or INCLUDES) should then be computed by assembling 
fragments, according to the tags attached to the files being compiled.

Maybe others could be interested in this approach, or would like to 
comment on it. So here is an example (the implementation is found below):

## New generic rules for compiling C code

ComputeCFLAGS(input) =
   CFLAGS += $(GetDynVarForTarget DYNCFLAGS, $(input))
   INCLUDES += $(GetDynVarForTarget DYNINCLUDES, $(input))
   value $(CFLAGS) $(addprefix $(INCLUDES_OPT), $(INCLUDES))

ComputesINCLUDES(input) =
   value $(GetDynVarForTarget DYNINCLUDES, $(input))

%$(EXT_OBJ): %.c :scanner: scan-c-%.c
   $(CC) $(ComputeCFLAGS %.c) -c $(CCOUT)$@ $<

SCANNER: scan-c-%.c: %.c /.PHONY/CGeneratedFilesTarget :value: 
$(digest-in-path-optional $(ComputesINCLUDES %.c), $&)
     $(CC) $(ComputeCFLAGS %.c) -MM $<
export


## A tag to specify that some C files implement stub code for OCaml.

AddDynVar(DYNCFLAGS, OCamlCStub, $(BYTECCCOMPOPTS))
AddDynVar(DYNINCLUDES, OCamlCStub, $(LIBDIR))

OCamlCStub(files) =
   TagFiles(OCamlCStub, $(addsuffix .c, $(files)))
   return $(addsuffix $(EXT_OBJ), $(files))


## Use this tag

OCamlCStub($(BINDINGS))
DynamicCLibrary(dllnumerics, $(BINDINGS))


===============================================================================

Here is the implementation of the tag system. Tags are materialized as 
empty files (in the tags/ subdirectory). Attaching a tag to a file is 
implemented by creating a dependency from the file to the tag. Dynamic 
variables are stored in map objects that associate command-line 
fragments to possible tags.


## Tags

section
   CREATE_SUBDIRS = true
   .SUBDIRS: tags
     %.tag:
       touch $@

TagMarker(tag) =
   value $(file $(ROOT)/tags/$(tag).tag)

## Get the value for a dynvar for some tag

GetDynVar(var, tag) =
   result =
   try
     map = $(getvar $(var))
     result = $(map.find $(tag))
   catch Exception(v)
   value $(result)

## Get the value for a dynvar, considering the tags attached to some target

GetDynVarForTarget(var, target) =
   result =
   foreach (tag, $(dependencies $(target)))
     result += $(GetDynVar $(var), $(tag))
     export
   value $(result)

## Extend the value for a dynvar for some tag

AddDynVar(var, tag, val) =
   if $(not $(defined $(var)))
     setvar($(var), $(Map))
     export
   private.tag = $(TagMarker $(tag))
   private.oldmap = $(getvar $(var))
   private.newmap = $(oldmap.add $(tag), $(GetDynVar $(var), $(tag)) $(val))
   setvar($(var), $(newmap))
   export

## Add a tag to a set of files

TagFiles(tag, files) =
   files = $(file $(files))
   tag = $(TagMarker $(tag))
   foreach(name, $(files))
     $(name): $(tag)
   value $(files)


-- Alain



More information about the Omake mailing list