On my 4-way Linux box calling an OMake function in a rule body
serializes an otherwise parallel build. The following OMakefile
reproduces the behavior.
.LANGUAGE: program
iota(n) =
iter(a, x) =
if ge(x, n)
return a
else
return iter(array(a, x), add(x, 1))
init[] =
return iter(init, int(0))
write_script_file(a_filename) =
fprint(a_filename, $'''#! /bin/sh
sleep 1
cp $1 $2
''')
filenames = addprefix($'a', iota(8))
source_ext = $'.s'
direct_target_ext = $'.d'
procedure_target_ext = $'.p'
function_target_ext = $'.f'
sources = addsuffix(source_ext, filenames)
direct_targets = addsuffix(direct_target_ext, filenames)
procedure_targets = addsuffix(procedure_target_ext, filenames)
function_targets = addsuffix(function_target_ext, filenames)
.LANGUAGE: make
lock_file = lock
script_file = sleep-and-copy.sh
command = flock --no-fork --timeout=0.25 --verbose $(lock_file) /bin/sh $(script_file)
.PHONY: gen
.DEFAULT: gen
gen:
touch $(sources)
write_script_file($(script_file))
.PHONY: clean
clean:
rm -f *$(direct_target_ext)
rm -f *$(function_target_ext)
rm -f *$(procedure_target_ext)
rm -f $(lock_file)
.PHONY: distclean
distclean: clean
rm -f *$(source_ext)
rm -f $(script_file)
.PHONY: direct
direct: $(direct_targets)
.PHONY: proc
proc: $(procedure_targets)
.PHONY: func
func: $(function_targets)
## omake -j1 direct # Always works ok because of serial execution.
## omake -j9 direct # Intentionally fails, which proves the base
# case, i.e. the mutex correctly catches for the
# tests proper.
%$(direct_target_ext): %$(source_ext)
$(command) $< $@
f(a_source, a_target) =
$(command) $(a_source) $(a_target)
return # This `return' statement is necessary to expose
# the quirk. Without it, omake(1) complains
# `command not found in PATH: ' when using
# function-call syntax (but not procedure-call
# syntax).
## Using procedure-call syntax `function(arg...)' makes the function
## call *not* interfere with parallelization is expected; it mimics
## direct execution.
##
## omake -j1 proc # Again, always works ok because of serial
## # execution.
## omake -j9 proc # Fails as expected.
%$(procedure_target_ext): %$(source_ext)
f($<, $@) # Respects parallel execution.
## Using function-call syntax `$(function arg ...)' blocks
## parallelization.
##
## omake -j1 func # Serially builds the targets as its `direct'
## # equivalent.
## omake -j9 func # Implicitly serializes the build, thus the
# build succeeds, where it should fail instead.
%$(function_target_ext): %$(source_ext)
$(f $<, $@) # Ignore any returned value from `f'?
To verify a truly parallel command execution at shell level, we call
flock with a command that certainly takes longer than the
timeout of flock. Use omake gen to create a starting
configuration.
Phony target direct evaluates command without any function call
interposed, so if everything is set up correctly
omake -j1 direct
builds all .d files and
omake -j9 direct
fails because the mutex ("lock") cannot be acquired.
Target func does not call command, but function f, which in turn
calls command. Here, both
omake -j1 func
and
omake -j9 func
succeed and build all .f files.
Curiously, in our example, phony target proc, which calls function
f with "procedure call" syntax
f(arg...)
in contrary to "function call" syntax of func
$(f arg...)
duplicates the findings of direct, this is, does not interfere with
parallel execution, as expected.
On my 4-way Linux box calling an OMake function in a rule body serializes an otherwise parallel build. The following OMakefile reproduces the behavior.
To verify a truly parallel command execution at shell level, we call flock with a
command
that certainly takes longer than the timeout of flock. Useomake gen
to create a starting configuration.Phony target
direct
evaluatescommand
without any function call interposed, so if everything is set up correctlybuilds all .d files and
fails because the mutex ("lock") cannot be acquired.
Target
func
does not callcommand
, but functionf
, which in turn callscommand
. Here, bothand
succeed and build all .f files.
Curiously, in our example, phony target
proc
, which calls functionf
with "procedure call" syntaxin contrary to "function call" syntax of
func
duplicates the findings of
direct
, this is, does not interfere with parallel execution, as expected.