Noob Doob
Noob Doob

Reputation: 1907

Makefile - set value to variable from another rule

In the following makefile, the wat rule is for producing a .wat file from a .c file.

CC=emcc
CFLAGS= -O2 -s WASM=1 -s SIDE_MODULE=1
# flags are for not generating any emscripten glue code

# makes a .wat version of a .c file of specified name
# TARGET must be specified from command line
wat: $(TARGET).c
    $(CC) $(CFLAGS) -o $(TARGET).wasm $(TARGET).c && wasm2wat $(TARGET).wasm > $(TARGET).wat && rm $(TARGET).wasm

struct: TARGET = struct
struct: wat

clear:
    rm -f *.wasm *.wat

Called like this, it works fine:

[user@pc]$ make wat TARGET=struct
emcc -O2 -s WASM=1 -s SIDE_MODULE=1 -o struct.wasm struct.c && wasm2wat struct.wasm > 
struct.wat && rm struct.wasm

Now I want a more specific rule, struct, written as you see. In essence, I want to reuse the wat rule, and just make sure that TARGET is set to 'struct' before running. However, running make struct gives me a no input file error from emcc, as if the value of TARGET does not exist:

[user@pc]$ make struct
emcc -O2 -s WASM=1 -s SIDE_MODULE=1       -o .c
shared:ERROR: no input files

What is the correct way to do what I aim?

Upvotes: 0

Views: 147

Answers (2)

Ondrej K.
Ondrej K.

Reputation: 9664

The problem is, that when make evaluates how to make targets and what the prerequisites are, your TARGET is undefined and hence the rule says: wat needs .c. You could try recursion and say something like this:

struct:
        $(MAKE) TARGET=struct wat

It really isn't that great to start with, because nothing actually generates file wat so the target is always out of date and the Makefile really is just a somewhat glorified shell script.

You should probably consider writing a pattern rule how to build .wat from .c, something like (based on your example):

%.wat: %.c
        $(CC) $(CFLAGS) -o $(*F).wasm $< \
                && wasm2wat $(*F).wasm > [email protected] \
                && rm $(*F).wasm

You then can call make struct.wat and if you still wanted (for convenience) have just struct target, you could add:

.PHONY: struct

struct: struct.wat

Upvotes: 1

MadScientist
MadScientist

Reputation: 100781

You appear to be attempting to use target-specific variables and in particular, their inheritance feature, to achieve your goal.

However, this cannot work because of this statement in the documentation:

As with automatic variables, these values are only available within the context of a target’s recipe (and in other target-specific assignments).

This means that the $(TARGET) in the prerequisite:

wat: $(TARGET).c

is evaluated when the makefile is parsed, not when the struct rule is invoked, and expands to:

wat: .c

I see that Ondrej provided an answer so I'll stop here :)

Upvotes: 1

Related Questions