dockernpmmakefile

Concatenate a string and run it as a command in Makefile (the first double dash disappears)


Sorry for my english in advance.

I've got nothing installed locally on my pc except the docker. For example, I prefer running npm commands in Makefile like this:

#!/usr/bin/make

TAG := 20.6.0
USER := $(shell id -u)
GROUP := $(shell id -g)
PROJECT_DIR := $(shell pwd)
TIMEZONE := $(shell cat /etc/timezone)
HOME:= /nodejs
PROJECT_NAME ?= some_project

npm := docker run --rm -ti \
    --name $(PROJECT_NAME) \
    --volume $(PROJECT_DIR):/nodejs \
    --volume /etc/passwd:/etc/passwd:ro \
    --volume /etc/group:/etc/group:ro \
    --user $(USER):$(GROUP) \
    --workdir $(SRC) \
    --env HOME=$(HOME) \
    --env TZ=$(TIMEZONE) \
    --network host \
    node:$(TAG) npm

# install npm dependencies
npm-i:
    $(npm) install

# build
build:
    $(npm) run build


# And many other commands...

Then later I tried to write one universal command like this (some stuff taken from here: How to pass argument to Makefile from command line?):

#!/usr/bin/make
TAG := 20
THIS_DIR := $(shell pwd)
USER := $(shell id -u)
GROUP := $(shell id -g)
HOME := /nodejs
PROJECT_NAME ?= some_project

npm_cmd:
    docker run -it --rm \
        --name $(PROJECT_NAME) \
        -v $(PROJECT_DIR):/nodejs \
        -v /etc/passwd:/etc/passwd:ro \
        -v /etc/group:/etc/group:ro \
        -u $(USER):$(USER) \
        -w $(HOME)/$(PROJECT_NAME) \
        --env HOME=$(HOME) \
        --network host \
        node:$(TAG) npm $(CMD)

.PHONY: npm

# Allows passing additional arguments to npm
npm:
    $(MAKE) npm_cmd CMD="$(filter-out $@,$(MAKECMDGOALS))"

%:
    @: # explained here: https://stackoverflow.com/questions/6273608/how-to-pass-argument-to-makefile-from-command-line

So now I run the commands like this:

make npm install

#or

make npm run build

But I encountered an issue with the npm run dev command and here is why. Usually I run it npm run dev -- --host or npm run dev -- --host --port 3000 and the problem is in first double dash after dev.

This first double dash is somehow cut after running.

enter image description here

I guess filter-out should be substituted with another stuff. Please help me add dashes to $(CMD). I don't want to change node:$(TAG) npm $(CMD) to node:$(TAG) npm $(CMD) -- --host. Thanks!


Solution

  • A double-dash by itself is a special token to every single command that conforms to the POSIX standard for argument parsing. That's why you're using it yourself, after all. But just like it's special to npm, it's also special to make in the same way: just like with npm it means that make should not parse any further arguments as options.

    So if you run make -k then make interprets the -k as an option (keep going). If you run make -- -k then make interprets the -k as a target to be built, just like with any other non-option argument that is not a variable assignment.

    If you want to be sure that ALL options, including -- are treated as arguments you need to put -- before them, like this:

    make -- npm run dev -- --host
    

    However, I agree with the comments above: this is not a good use of make. Make's command line is intended for make, not for passing other options.

    I would think it would be a whole lot simpler, and more direct, to use a shell script for this rather than a makefile.