Can I use the target name in a target-specific variable?
program_%: CFILE=path/program_%/do_it.c
^^^^^^^^^^
This does not work
So that when doing "make program_xyz", the CFILE will be "path/program_xyz/do_it.c".
It depends on what you want to use CFILE for. Since you gave us no details about that I'll just answer your exact question: sure, you can do that:
program_% : CFILE = path/program_$*/do_it.c
program_% : ; #echo $(CFILE)
$ make program_foo
path/program_foo/do_it.c
However, my suspicion is you wanted to do more with CFILE besides simply use it inside this recipe. If so, the above solution my not work for what you really want to do...
Related
I am designing a simple makefile that defines one target which takes an argument, and I would like to define a second target that invokes the first target in a loop, once per every variable defined in an array variable at the top of the Makefile.
my_loop_var = var1 var2
my_thing:
echo $MY_VAR
all:
invoke my_thing once for each value of my_loop_var
What is the right way to solve this?
Note: $MY_VAR will probably expand as Y_VAR because make will try to expand variable M, which is probably undefined, and concatenate Y_VAR to the result. Use $(VARNAME) to expand make variable VARNAME. It is only with single-character variable names that you can expand with $X.
There is not really a "right way". There are many ways. The most straightforward from your specifications (but the less natural) would be something like:
my_loop_var := var1 var2
my_thing:
echo "$(MY_VAR)"
.PHONY: all my_thing
all:
for v in $(my_loop_var); do $(MAKE) my_thing MY_VAR="$$v"; done
The recipe of all is a shell loop that re-invokes make with the my_thing goal and with each value in my_loop_var passed as the value of make variable MY_VAR.
Note the $$v to escape the first expansion that make always performs before passing the recipe to the shell. With just $v make would expand the recipe as ... MY_VAR="" ... and the result would not be what you expect.
Note also the use of the MAKE make variable instead of directly calling make (have a look at the documentation if you want to understand why it is better like this).
all and my_thing are declared as phony because they are not real file names that their recipes create, and make needs to know this kind of things.
But a much more make-ish way would be something like:
my_loop_var := var1 var2
my_thing_targets := $(addprefix my_thing_,$(my_loop_var))
.PHONY: all $(my_thing_targets)
all: $(my_thing_targets)
$(my_thing_targets): my_thing_%:
echo "$*"
Here we define as many my_thing_something targets as there are something values in my_loop_var. And explain make how to build such targets with a static pattern rule. In the recipe of a pattern rule the $* automatic variable expands as the part that matched the % pattern. So, this static pattern rule says that if we need to build my_thing_something, the recipe is echo "something".
We declare all these my_thing_something targets as prerequisites of all such that if you type make or make all, make will build all the my_thing_something targets.
This second solution is better for at least two reasons. First, make is invoked only once, which is better, at least for performance. Second, make can parallelize the build of the my_thing_something if you use the -j N option (to allow make to run up to N jobs in parallel). This also is better for performance.
But it is also a matter of style. Very frequently if you use shell loops in your recipes, especially to invoke make again, it is the sign that you did not really understand what make is intended for and how it works. The make language is not a scripting language (even if the recipes are written in shell language, which is a scripting language); make is designed to "loop" over all targets to build, without the need for explicit loops.
Haven't been using make for a while. But just got a project from a 10 years old compiler using Ubuntu.
I am looking at the makefile and trying to find out which compiler it is using.
${MAKE} is used in the file.
But where can I find out the definition of MAKE.
Thanks
You could simply use both the info and value built-in functions inside your makefile:
$(info MAKE: $(value MAKE))
This will work if MAKE is a recursively expanded variable, which it is by default. Otherwise, if MAKE were a simply expanded variable, you will see the expansion that was done at the moment of evaluating MAKE's definition (i.e., the same as $(MAKE)).
A better approach, which is independent of the flavour of the variable, would be to run make with the option -p and look at the definition of MAKE, e.g.:
make -p | grep 'MAKE ='
You will probably find out that MAKE is defined as:
MAKE = $(MAKE_COMMAND)
and MAKE_COMMAND, which is another variable (this time, a simply expanded one), may be in turn defined as:
MAKE_COMMAND := make
My idea is to use computed names to emulate namespaces, for example:
GetVar = $(or $($2#$1),$($2))
fubar#namespace = foo bar
frob = baz
$(info $(call GetVar,namespace,fubar))
$(info $(call GetVar,namespace,frob))
furthermore this could be used in rules to have target local variables
cmd#target = echo hello
target:
$(call GetVar,$#,cmd)
This seem to work on GNU-make, but it raises a few questions:
First of all this will result in using non-normal characters in variable names. Of course one may use another separator than #, but in using the target name as the namespace name you would inevitably run into cases where dots and slashes end up in the variable name. How bad is this? The GNU-make manual tells me to avoid this and mentions the ability to share this via environment to submakes, but this is in a non-recursive makefile setup.
Is this exploiting a non-portable feature of GNU-make? Need I be concerned with feature versions of make breaking this feature?
Is there any example of this idiom actually being used? Not being able to find any cases makes me wonder if there's anything I've missed that makes this a bad idea.
If it's not that bad idea, are there any particular namespace separator that would be more suitable than other?
As far as I can see you're mostly recreating target-specific variables. Is there some reason you don't want to use them?
target: cmd = echo hello
target:
$(cmd)
I want to set a variable depending on the assigned target.
For instance:
if target == filename_a then
VAR1 = YES
if target == filename_b then
VAR2 = YES
Obviously, this is pseudo-code and not proper make-syntax.
What I really want to do is to include different make-files and include-directories dependent on target. Some targets share the same settings, and hence it is easier to maintain in one makefile.
An example of what it will be used for later:
ifeq ($(VAR1), YES)
include foo.mk
endif
ifeq ($(VAR2), YES)
include baz.mk
endif
Unfortunantly the following syntax cannot be used:
target : VAR1 = YES
Since this variable assignment is only valid through the process of actually building target, as I understand it.
The target environment is ClearMake 7 under Solaris, so please avoid any GNU Make specific solutions.
Thanks
Edit:
As far as I can tell, make does not work in a way where the target is available during the processing step. Hence the feature asked for does most likely exist.
I'd be surprised if this can work, since as I understand it, Make processes include statements before it knows what targets it needs to make. But I know nothing about ClearMake and I'm not really an expert, so hopefully someone proves me wrong...
I am looking at C makefile, and I have a question.
I know that 'make a' will make the target a, which is supposed to be defined in the makefile.
I want to know whether the target name itself can be supplied as an argument to make.
i.e. this is what I want to do:
$(target_name) is the name supplied to command 'make'. For example, 'make foo'.
and in the makefile,
$(target_name) = dependencies
command
I am not sure whether this is possible... could not find anything in the make manual too.
If anyone can help me with this, it'll be awesome.
Thanks,
Everything you are asking about is what make does by default - there is no need to write any special code in the makefile to do this. You seem rather confused about make (it is not particularly C related, for example). The best guide to it is the GNU Make Manual, which is not only a manual but a pretty good tutorial.
I'm kind of new to Makefiles but it seems you don't pass values in Makefile like that. If the following is your Makefile
# Makefile
TARGET?=something
$(TARGET):
echo $(TARGET)
You can pass parameters in by calling make like this in the terminal
$ TARGET='ABCDEF' make