[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Rename positional parameters in customized GNU make functions to enh
From: |
Kaz Kylheku (gmake) |
Subject: |
Re: Rename positional parameters in customized GNU make functions to enhance readability and maintainability. |
Date: |
Fri, 21 Jan 2022 08:10:12 -0800 |
User-agent: |
Roundcube Webmail/0.9.2 |
On 2022-01-21 02:34, Hongyi Zhao wrote:
I try to redefine the download_and_unpack function used here [1] as
follows:
```
define download_and_unpack
@package := $(1)
^
What is that? Is this supposed to be the echo suppressing character used
in recipe lines?
You seem to have a misconception about how make works.
You cannot assign variables in makefile recipes; they are shell scripts.
Variable assignments are processed when a Makefile is parsed by make,
before
recipes execute. During execution of recipes, target-specific variables
are set at run-time and expanded in the recipe and of course special
ones
like $@ and $<.
No assignment syntax is available in a recipe line.
@package_URL := $(2)
@package_directory := $(3)
@package_code := $(4)
@package_archive := ../archive/`echo "$(package)" | sed
's/.*\///;s/.*=//'`
You could do this with shell variables. But since recipe lines
are run in separate shell invocations, shell variables set in one
line cannot be seen in another (unless you globally override that
with .ONESHELL:, which I wouldn't recommend in an existing, complex
Makefile that you're trying to customize).
You can do it like this:
define big_recipe_macro
arg1=$(1) \
arg2=$(2) \
... = ... \
( command1 $$arg1 $$arg2 && \
command1 --foo $$arg2 $$arg3 && \
... )
endef
Don't forget that double $$ are needed in a macro to pass a single $
to the macro expansion.
Now, here is a topic on a tangent, which may be relevant.
In Makefiles which work with tuples of variables which are related,
you can use named variables to simulate a data structure.
If I were developing a Makefile in which there is a "package" concept
which has properties like "directory", "URL", and so on, here is
what I would do:
Have a place where the database is declared. This could be scattered in
multiple include makefiles:
# define package foo
foo.name := "foo"
foo.version := 1.2
foo.url := "https://foo.org/downloads/foo-$(foo.version).tar.gz"
foo.directory := "packages/$(foo.name)"
# define package bar
bar.name := "foo"
bar.version := 4.7.1
bar.url := "https://bar.com/packages/bar-$(bar.version).tar.xz"
bar.directory := "packages/$(bar.name)"
How named variables work is that we can have the package name in
a variable, e.g.:
package=foo
so now to access $(foo.version), we can do this:
$($(package).version)
Make will expand $(package) to foo, so this becomes $(foo.version)
and that then expands to 1.2.
Now you can use a single parameter in a recipe macro, so that
$(1) gives the package name:
define download_and_unpack
cd $((1).directory) && wget $($(1).url) -o $($(1).directory)
...
endef
Still pretty ugly, but at least the property system is more or less
clearly organized.