[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