Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 452
sebastian_t Avatar asked Aug 28 '18 14:08

sebastian_t


People also ask

Can we pass arguments to makefile?

@smarber You can't pass arguments to make without make interpreting them as its own command line flags, targets or variable assignments.

What is $@ in makefile?

$@ is the name of the target. This is quite useful when the target is a pattern rather than fixed. $^ is the name of the prerequisite that caused the rule to execute.

How do I call a target in makefile?

When you type make or make [target] , the Make will look through your current directory for a Makefile. This file must be called makefile or Makefile . Make will then look for the corresponding target in the makefile. If you don't provide a target, Make will just run the first target it finds.


Video Answer


2 Answers

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.

like image 140
MadScientist Avatar answered Nov 07 '22 07:11

MadScientist


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.

like image 33
HardcoreHenry Avatar answered Nov 07 '22 09:11

HardcoreHenry