subst "/dev/ttyPS1" to \""/dev/ttyPS1\"" in makefile - makefile

I'm trying to perform this substitution without any success with the following,
a="/dev/ttyPS1"
b=$(patsubst \"%\",\\\"\"%\\"\",$(a))
c=$(subst \",\\\"\",$(a))
$(info $(a) $(b) $(c))
Output :
$ make
"/dev/ttyPS1" "/dev/ttyPS1" "/dev/ttyPS1"
Desired Output :
$ make
"/dev/ttyPS1" \""/dev/ttyPS1\"" \""/dev/ttyPS1\""
I must be doing something dumb with the escape sequences since it doesn't appear to change at all... I don't have any preference on how I get there (patsubst, subst, or other). Any ideas? Thanks.

You don't need to escape quotes with backslashes in make syntax: quotes are not special to make. Thus your subst of \" never matches because there's no two-character string \" in the string "/dev/ttyPS1".
Try:
a = "/dev/ttyPS1"
b = $(patsubst "%",\""%"\",$(a))
c = $(subst ",\"",$(a))
$(info $(a) $(b) $(c))

Related

make/gmake: given a variable starting with multiple ../, create a variable with one less ../

Given a variable, how can I create another variable with the leading repetitions of ../ that the first variable starts with, albeit with one less repetition?
For instance, given ../../../foo/bar, how do I end up with ../../?
I've tried a perl regexp like perl -e '$a = "../../../foo/bar"; $a =~ /^\.\.\/((\.\.\/)+)/; print "$1\n"' but can't figure out the magic incantation of quotes, backslashes, dollar signs, and so on needed to run it within $(shell).
Further I suspect there's a simpler way to do it.
This will remove one ../ at the front: $(patsubst ../%,%,$(ORIGINAL_PATH))
To isolate the first streak of ../ one could go as follows:
space := $(strip) $(strip)#
FIRST_STREAK := $(firstword $(subst $(space)../,../,$(subst ../,../$(space),$(ORIGINAL_PATH))))
Let's write this as a function:
space := $(strip) $(strip)#
UP_PATH = $(patsubst ../%,%,$(firstword $(subst $(space)../,../,$(subst ../,../$(space),$1))))
Test it:
ORIGINAL_PATH := ../../../foo/bar/../baz
$(info $(call UP_PATH,$(ORIGINAL_PATH)))
Output:
../../

Make args: is there a variable that contains all of them?

In make, I can define a file as follows:
.PHONY: echo-foo
echo-foo:
echo ${foo}
Usage:
make echo-foo foo=foo
Now suppose I would like to do the following:
make echo-vars foo=foo bar=bar
And I start by writing:
echo-vars:
echo ${???}
Is there a variable automatically defined which will output:
// either
foo=foo bar=bar
// or
foo bar
In other words: is there a MAKEARGS or some variable along those lines defined as part of the make env?
There's a special variable just for that:
echo-vars:
echo ${MAKEOVERRIDES}
.VARIABLES is somewhat close.
This prints only command-line variables:
test:
echo "$(foreach VAR_NAME,$(.VARIABLES),\
$(if $(filter command line,$(origin $(VAR_NAME))),$(VAR_NAME)))"
$(filter command line,$(origin VAR_NAME)) equals to "command line" if it's the value of $(origin VAR_NAME), and is empty otherwise. $(filter <needle>,<haystack>) is a make's boolean test for "<needle> is in or equals to <haystack> and is not empty".
$(if <condition>,<value>) returns <value> if <condition> is nonempty, otherwise an empty string.
$(foreach VAR_NAME,SET,EXPRESSION) returns a joined result of EXPRESSION applied to each element of a (space-separated) SET, where VAR_NAME is substituted with each element of the SET.
Add $(strip) to get rid of excess spaces.

How to trim a string in makefile?

I have this string cccccc:dddddd
I want to get cccccc only
I looked at makefile docs but still confused how to do this with make functions
This doesn't work but I want to do something like match from : to end of line and trim all of that
MY_VAR:=cccccc:dddddd
....
derp:
echo $(subst :.*,"",$(MY_VAR))
:dddddd is not static so I cant just hardcode that in like $(subst :dddddd,"",$(MY_VAR))
You can try something like:
MY_VAR := $(firstword $(subst :, ,$(MY_VAR))
Note this requires that "cccccc" does not contain whitespace.

How to concatenate strings in a Makefile?

I have a Makefile that runs pandoc. I want to turn a list of extensions:
PANDOC_EXTENSIONS = \
multiline_tables \
some_other_extension
into a string that looks like:
PANDOC_EXTENSION_LIST = +multiline_tables+some_other_extension
which will then be passed as a command line option to pandoc like this:
pandoc --from$(PANDOC_EXTENSION_LIST) ...
It's trivial in almost any programming language, but I can't figure out how to do this with the patsubst or subst functions, since make doesn't really have lists. Any ideas?
Here:
Makefile
PANDOC_EXTENSIONS = \
multiline_tables \
some_other_extension
$(foreach word,$(PANDOC_EXTENSIONS),$(eval PANDOC_EXTENSION_LIST := $(PANDOC_EXTENSION_LIST)+$(word)))
.PHONY: all
all:
echo $(PANDOC_EXTENSION_LIST)
Which runs like:
$ make
echo +multiline_tables+some_other_extension
+multiline_tables+some_other_extension
As this illustrates, GNU make really does have lists. A sequence of whitespace-separated words is a list.
Based on example in documentation:
empty:=
space:=$(empty) $(empty)
PANDOC_EXTENSIONS = \
multiline_tables \
some_other_extension
all:
#echo +$(subst ${space},+,${PANDOC_EXTENSIONS})
The result:
$ gmake
+multiline_tables+some_other_extension

gnu make: list the values of all variables (or "macros") in a particular run

How can I list the current value of all variables (also called macros) in a Makefile when running make?
E.g. if this is in the Makefile:
CUR-DIR := $(shell /bin/pwd)
LOG-DIR := $(CUR-DIR)/make-logs
Then I would like it to tell me:
CUR-DIR = /home/johv/src/test
LOG-DIR = /home/johv/src/test/make-logs
GNU make provides .VARIABLES
which holds all global variables' names.
However, this includes built-in variables(like MAKEFLAGS).
If you have to exclude built-in variables, some filtering like the following
might be needed.
The following makefile prints user-defined variables(CUR-DIR, LOG-DIR)
using info:
# Place this line at the top of your Makefile
VARS_OLD := $(.VARIABLES)
# Define your variables
CUR-DIR := $(shell pwd)
LOG-DIR := $(CUR-DIR)/make-logs
# Put this at the point where you want to see the variable values
$(foreach v, \
$(filter-out $(VARS_OLD) VARS_OLD,$(.VARIABLES)), \
$(info $(v) = $($(v))))
Thanks to #Ise Wisteria, condensed down, this shows all variables, useful for large projects with multiple makefiles (Buildroot).
$(foreach v, $(.VARIABLES), $(info $(v) = $($(v))))
output: BR2_GCC_TARGET_TUNE = "cortex-a8" ...
If you get an error like: insufficient number of arguments (1) to function 'addprefix' this project had some broken variables... I trimmed the list of variables to show, only with a prefix BR2_
$(foreach v, $(filter BR2_%,$(.VARIABLES)), $(info $(v) = $($(v))))
I ended up doing it like this:
gmake -pn | grep -A1 "^# makefile"| grep -v "^#\|^--" | sort | uniq > makevars.txt
which gives:
CUR-DIR := /home/johv/src/test
LOG-DIR := /home/johv/src/test/make-logs
MAKEFILE_LIST := Makefile
MAKEFLAGS = pn
SHELL = /bin/sh
VARS_OLD := [...]
gmake -pn is really verbose and looks kinda like this:
# environment
GNOME2_PATH = /usr/local:/opt/gnome:/usr:/usr/local:/opt/gnome:/usr
# automatic
#F = $(notdir $#)
# makefile
SHELL = /bin/sh
# default
RM = rm -f
It's also doable without saving all the .VARIABLES and filtering them out.
Moreover, if one of the original .VARIABLES was modified in your makefile, the two most voted answers won't catch it.
Check out $(origin) function. This target filters out and prints all the variables that were defined in a makefile:
print_file_vars:
$(foreach v, $(.VARIABLES), $(if $(filter file,$(origin $(v))), $(info $(v)=$($(v)))))
I get only a few excess variables this way: CURDIR SHELL MAKEFILE_LIST .DEFAULT_GOAL MAKEFLAGS.
One can replace file with environment or command line to print the respective kinds of variables.
There are a lot of good answers here, but you're going to have problems using $($(v)) if some of your variables are of the recursive flavor. This is why you should use $(value $(v)).
This variation cleans this up a little bit, sorts variables by name and makes the output a bit more readable.
dump:
$(foreach v, \
$(shell echo "$(filter-out .VARIABLES,$(.VARIABLES))" | tr ' ' '\n' | sort), \
$(info $(shell printf "%-20s" "$(v)")= $(value $(v))) \
)
Thanks to #kevinf for the great idea. I would suggest a minor change to prevent .VARIABLE itself from printing out in the variable list:
$(foreach v, $(filter-out .VARIABLES,$(.VARIABLES)), $(info $(v) = $($(v))))
Thanks to #kevinf for the foreach solution -- if one wants to export this list as a somewhat machine-readable file, one will have a hard time with uneven quotes or newlines when using echo or printf, since Make isn't able to quote the data correctly -- one needs to use the $(file ...) function to write the data to avoid sh/bash complaining about invalid syntax. For example, use this in your rule -- it prints variable name, definition and expanded value:
$(file > $(MAKEFILE_ENV_FILE),)
$(foreach v, $(.VARIABLES), \
$(file >> $(MAKEFILE_ENV_FILE),$(v)) \
$(file >> $(MAKEFILE_ENV_FILE), := $(value $(v))) \
$(file >> $(MAKEFILE_ENV_FILE), == $($(v))) \
$(file >> $(MAKEFILE_ENV_FILE),) \
)
(This will still not allow to always distinguish malicious variables with double newlines from two variables, for this one now add a sufficiently unique separator infront of each Makefile-generated newline just after each comma inside $(file >> NAME,TEXT))
Set MAKEFILE_ENV_FILE to some filename, e.g.:
MAKEFILE_ENV_FILE := $(abspath $(lastword $(MAKEFILE_LIST))).env

Resources