Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force make not to re-order pre-requisites in automatic variable expansion

Here a is my makefile (GNU make) to compile a small OCaml program:

SUFFIXES:=
OCAML=ocamlopt
LD=ocamlopt
OFLAGS=

.PHONY: all clean

all: playground

playground.cmx: playground.ml lstream.cmi
playground: lstream.cmx playground.cmx

%.cmi: %.ml
    $(OCAML) $(OFLAGS) -c $<

%.cmx: %.ml
    $(OCAML) $(OFLAGS) -c $<

%: %.cmx
    $(LD) -o $@ $^

playground uses functions from the Lstream module. In this case, the ocaml linker requires the files to link to be specified in order of dependency (eg: ocamlopt -o playground lstream.cmx playground.cmx).

Despite the fact that I defined the playground rule's dependencies in the right order, make consistently re-orders them and executes ocamlopt -o playground playground.cmx lstream.cmx which causes a linker error.

Is there a way to enforce the correct behaviour ? I would like to avoid specifying the link command explicitely and let make infer it from the dependencies.

like image 570
lbonn Avatar asked Feb 02 '26 01:02

lbonn


1 Answers

Implicit rules always force the pattern matching prerequisite to be first, regardless of the order in which they're defined elsewhere. This is almost always what you want, because in most rules the pattern matching prerequisite is special.

For example when compiling an object file the prerequisites consist of one source file and a bunch of header files; the source file is special and needs to be listed on the command line. Make ensures that for a pattern rule %.o : %.c (for example) the prerequisite matching %.c is first in the list, and so is assigned to the $< automatic variable, and it can be treated differently.

In any event the short answer is no, you cannot modify this behavior. An implicit rule % : %.cmx matching a target playground will always force the prerequisite playground.cmx to be listed first in the prerequisite list. The other prerequisites will maintain their order.

If you really need the prerequisites to maintain their order then I recommend using a static pattern rule:

TARGETS = playground

$(TARGETS) : % :
        $(LD) -o $@ $^

(you can also use a "match anything" pattern rule but this can be a real performance degrader). Here since you have no pattern in the prerequisite list, nothing will be reordered.

like image 121
MadScientist Avatar answered Feb 03 '26 20:02

MadScientist



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!