sebastian_t
sebastian_t

Reputation: 2869

Makefile passing additional arguments to targets command from make command

I have a Makefile that defines docker-compose project. It essentially assembles me a command:

COMMAND := docker-compose --project-name=$(PREFIX) --file=$(FILE_PATH)

up:
    $(COMMAND) up -d

I would like to add a target named dc to which I would be able to pass any arguments I want.

I know there is one solution:

target:
    $(COMMAND) $(ARGS)

And then call it with make target ARGS="--help" for example.

But isn't there an easier way like in bash $@ ? I would like to skip the ARGS=... part and send everything to the command after target name.

Upvotes: 10

Views: 21761

Answers (4)

izissise
izissise

Reputation: 953

A target that re-run make containerized

.PHONY: all containerized

ifeq ($(filter containerized,$(MAKECMDGOALS)),containerized)
.NOTPARALLEL: containerized
MAKEOVERRIDES ?=
containerized: ## Build inside a container
    @docker run image_with_make make $(MAKEOVERRIDES) $(filter-out containerized,$(MAKECMDGOALS))
else
# other targets here
all: xxxx

endif

Executing make containerized all runs make all in container

Upvotes: 1

msudder
msudder

Reputation: 512

The first answer is correct, no passthru of args. However, here is a plausible path for experimentation, use of branch by include selection:

# Makefile:

COMMAND := $(PYTHON) this_shit_got_real.py
LOCAL_MK ?= local.mk

# '-' important, absence of LOCAL_MK is not cause for error, just run with no overrides
- include $(LOCAL_MK)

target:
  $(COMMAND) $(ARGS)

Now see how you add branching with env:

echo "ARGS=--help">>local.mk
# make target

And the other cli controlled branch

echo "ARGS=--doit">>runner.mk
# LOCAL_MK=runner.mk make target

Upvotes: 0

MadScientist
MadScientist

Reputation: 100876

Not really. The make program interprets all arguments (that don't contain =) as target names to be built and there's no way you can override that. So even though you can obtain the list of arguments given on the command line (via the GNU make-specific $(MAKECMDGOALS) variable) you can't prevent those arguments from being considered targets.

You could do something like this, which is incredibly hacky:

KNOWN_TARGETS = target

ARGS := $(filter-out $(KNOWN_TARGETS),$(MAKECMDGOALS))

.DEFAULT: ;: do nothing

.SUFFIXES:
target:
        $(COMMAND) $(ARGS)

(untested). The problem here is you have to keep KNOWN_TARGETS up to date with all the "real" targets so you can remove them from the list of targets given on the command line. Then add the .DEFAULT target which will be run for any target make doesn't know how to build, which does nothing. Reset the .SUFFIXES meta-target to remove built-in rules.

I suspect this still will have weird edge-cases where it doesn't work.

Also note you can't just add options like --help to the make command line, because make will interpret them itself. You'll have to prefix them with -- to force make to ignore them:

make target -- --help

Another option would be to add a target like this:

target%:
        $(COMMAND) $*

Then you can run this:

make "target --help"

But you have to include the quotes.

In general I just recommend you reconsider what you want to do.

Upvotes: 6

HardcoreHenry
HardcoreHenry

Reputation: 6387

You could write a bash wrapper script to do what you'd like:

#/bin/bash
make target ARGS=\"$@\"

The reason you don't want to do it in make, is that make parses the command line parameters before it parse the makefile itself, so by the time you read the makefile, the targets, variables, etc have already been set. This means that make will have already interpreted the extra parameters as new targets, variables etc.

Upvotes: 5

Related Questions