Home > Software design >  How can I achieve $(<some-file) inside a Makefile target?
How can I achieve $(<some-file) inside a Makefile target?

Time:09-16

I am trying to implement the jq pipe curl command from https://docs.gitlab.com/ee/api/lint.html#use-jq-to-create-and-process-yaml--json-payloads but inside of a make file context.

I have spent hours trying seemingly every single permutation of escaping and trying substitute commands but I can't get the equivelant to work. I have no problem outside of makefile.

I tried substituting "$(<foo.yml)" with "$$(<foo.yml)" or $(shell cat foo.yml) and even cat foo.yml | ... @- but no luck. The shell cat was the closest I got but cat removes \n characters which then makes the resultant JSON that I pass to GitLab come back with confusing errors: {"valid":false,"errors":["(\u003cunknown\u003e): block sequence entries are not allowed in this context at line 1 column 12"],"warnings":[],"status":"invalid"}

I compared the string with the working original version outside of Makefile context and the only thing different is the lack of \n characters.

Please help! Thank you.

EDIT As requested, here are the extra details from the URL.

This is the command I am trying to move into a Makefile context. This command works fine from directly from my bash terminal.

jq --null-input --arg yaml "$(<.gitlab-ci.yml)" '.content=$yaml' | curl "https://gitlab.com/api/v4/ci/lint?" --header "Content-Type: application/json" --header "PRIVATE-TOKEN: $GITLAB_PERSONAL_ACCESS_TOKEN" --data @-

Here's the response: {"valid":true,"errors":[],"warnings":[],"status":"valid"}

Here is my Makefile version:

.PHONY: lint
make lint:
    jq --null-input '.content="$(shell cat "$(GITLAB_CI_FILE_PATH)")"' | curl --header "Content-Type: application/json" --header "PRIVATE-TOKEN: $(GITLAB_PERSONAL_ACCESS_TOKEN)" --data @- "https://gitlab.com/api/v4/ci/lint"

Here's the response: {"valid":false,"errors":["(\u003cunknown\u003e): block sequence entries are not allowed in this context at line 1 column 12"],"warnings":[],"status":"invalid"}

I know that this is because my makefile version does not contain newline characters.

Here is the input YAML file:

include:
  - project: adamcunnington.info/MLG/common
    file: /cicd/.gitlab-ci-python.yml

CodePudding user response:

It would be very helpful if you provide the complete rule you're trying to write.

Using $(<foo.yml) can't work in a make recipe because make treats everything starting with a $ as a make variable and expands it before running the shell. You need to escape all $ you want the shell to see, as $$.

Using $$(<foo.yml) will work on some systems, but not other systems: that syntax is not defined by the POSIX standard and so shells that provide POSIX features will not do anything with it. That's enhanced syntax for the bash shell. Make always runs /bin/sh by default, so if your /bin/sh is really bash, it might work. If not, not.

Using $(shell cat foo.yml) cannot work because make's shell function removes all newlines from the output before replacing it.

Since we can't see your actual rule we can't really suggest the best alternative. Is there some reason you can't use the simple, standard:

jq < foo.yml

?

ETA

As explained, your shell is bash. Make always by default uses /bin/sh as a shell (imagine the portability problems if make always used whatever shell the person invoking it was using).

If you can't figure out how to rewrite your makefile recipe to use standard POSIX syntax and you instead want to use bash-specific syntax, you can tell make to use bash as its shell:

SHELL := /bin/bash

now all the bash-specific magic will work in your recipes. Of course your makefile will not work on systems that don't have /bin/bash.

CodePudding user response:

A much simpler and more portable rearticulation of the jq part would be

jq --null-input --rawfile yaml .gitlab-ci.yml '.content=$yaml'

Inside a Makefile, obviously double the dollar sign.

A minor difference is that with --rawfile the final newline in the file is included, too.

The --rawfile option was introduced in jq 1.6.

  • Related