Set the default target(s) of a Makefile (GNU Make) via Environment Variable - gnu-make

I'd like to set the default target(s) of a Makefile to the space-deliminted value of an Environment Variable.
For this solution to work correctly, it must be possible for me to set an environment variable, then run make and have the target, (or optionally space-delimited targets), contained in the environment variable be used as though they were passed as targets.
DEFAULT_TARGETS="target target2" make
# ... should produce the same result as ...
make target1 target2
Thanks for the help!

You can do it by adding something like this to your makefile:
ifneq ($(DEFAULT_TARGETS),)
__default_targets: $(DEFAULT_TARGETS)
.DEFAULT_GOAL = __default_targets
endif

Following #Andreas lead I've landed on this ...
.PHONY: DEFAULT_TARGET
DEFAULT_TARGETS ?= intro
DEFAULT_TARGET: $(DEFAULT_TARGETS)
This use the "First Target as Default" paradigm, then expands the contents of the DEFAULT_TARGETS env-var to add requisites. It also has the advantage that if the DEFAULT_TARGETS environment variable is not set, the makefile will use the fall-back value, in this case that's intro.
In the shell this would look like, DEFAULT_TARGETS="target target2" make

Related

Add an extension in a .pro variable

I'm trying to print a message with QMake but I have problems with extensions:
lib_name = $$1
message("test1: $$MYPATH/$$lib_name/src/$$lib_name.pri");
message("test2: $$MYPATH/$$lib_name/src/$$lib_name");
For some reason, test1 doesn't print the correct path. It just prints the path until src/. But, test2 is ok. It prints everything until the value in $$1.
Any workaround?
QMake supports variables (objects) with members that can be used using the dot . operator e.g. target.path for INSTALLS. So, in your case, $$lib_name.pri means that you're accessing the member pri of lib_name which doesn't exist so there's no output.
You need to enclose variables in curly braces for QMake to distinguish them from the surrounding text i.e. $${lib_name}.pri.
Example:
message("test1: $$MYPATH/$$lib_name/src/$${lib_name}.pri");
# ~~~~~~~~~~~~
For more examples of objects, see Adding Custom Target and Adding Compilers sections of QMake's Advanced Usage page.
Here's another relevant SO thread: QMake - How to add and use a variable into the .pro file

GNU make: include file only if target is not "clean"

Using GNU make, I want to include a file, except if the current target is "clean".
That is, I want to do the equivalent of the following:
ifneq($(TARGET),clean)
-include somefile.txt
endif
But for that, I need a variable whose value is the target given on the command line (here named $(TARGET)). Such a variable does not seem to exist, and I can understand why, because you could have multiple targets on the command line, some of which you might want to include the file for, and others not. Actually, it would be fine if the file is included when there are other targets besides "clean". The only real problem I currently have is that when the file to be included does not exist, Make will try to build it, which is unnecessary when you're about to delete it again when executing the "clean" target.
So, is there another way to accomplish what I want?
You can use MAKECMDGOALS. Use it like this to handle multiple arguments on the command line:
ifeq (clean,$(filter clean,$(MAKECMDGOALS)))
-include somefile.txt
endif
However, this is often fraught because if you run make clean all or whatever, the include file won't be included even though it might be needed for all.
If you really need this to be reliable another way is to use recursion for your "top-level" arguments, running them one at a time in a sub-make.
You could usefully check that if clean is a target then it is the only target. Otherwise strange things can go wrong silently causing much wailing and gnashing of teeth. My most recent Makefile includes the following. (NB tested but not as yet used extensively).
ifeq (clean,$(filter clean,$(MAKECMDGOALS)))
ifneq($(strip $(filter-out clean,$(MAKECMDGOALS)))
$(error ERROR: can not make other targets with clean
endif
endif

Name for GNU Make $(var:=suffix) syntax

Evidently, GNU Make supports the syntax $(var:=suffix), which does the same thing as $(addsuffix suffix,$(var)) as far as I can tell, except that suffix can contain , in the := version without the use of a variable.
What is this form of expansion called?
Evidently it operates on whitespace-delimited words, producing a new string without modifying the original variable.
This file
# Makefile
words=cat dog mouse triangle
$(info $(words:=.ext))
$(info $(words:=.ext))
all:
#true
produces the following when run:
$ make
cat.ext dog.ext mouse.ext triangle.ext
cat.ext dog.ext mouse.ext triangle.ext

Can one append to a make variable without overwriting what's set in the Makefile?

Let's consider the following Makefile:
.PHONY : all
OPTS += -DBLA
OPTS += -DBLUBB
STUFF = default
all :
./do_something $(OPTS) $(STUFF)
One can pass variables on the command line. So with the following call
confus#confusion:/tmp/$ make STUFF=foo
make will run ./do_something -DBLA -DBLUBB foo.
Contrary to what I thought one can't append to variables:
confus#confusion:/tmp/$ make STUFF+=foo OPTS+=-DMOREOPT
will simply run ./do_something -DMOREOPT foo (as if I had left out the plus signs), when I'd expect it to ./do_something -DBLA -DBLUBB -DMOREOPT default foo.
Is there a way to append to a make variable with a command line option?
If this is GNU make, you have to use the override directive in your makefile to specify that you want the values set in the makefile to take precedence over the command line values:
override OPTS += -DBLA
override OPTS += -DBLUBB
override STUFF += default
If it matters, note that this will put the settings provided on the command line first, and the settings in the makefile last.

How to conditionally build target and all its dependencies based on values passed to variables in the command line?

I have looked at documentation of GNU Makefile Conditional Statements, but I couldn't find any information on how to build both the target and its dependencies conditionally.
EDIT: When I say conditionally, I mean dependent on values of variable set in command line while calling make. I apologize for not making it clear earlier.
To add to the above edit. If some variables set in the commandline take a particular value, even if the targets and their dependencies need to be updated, I want to refrain from doing this.
GNU Makefile Conditionals
Thanks!
What about something like:
ALL_TARGETS = foo bar
ifndef SOME_VARIABLE
ALL_TARGETS += biz baz
endif
all: $(ALL_TARGETS)
Now if you run make it will build foo, bar, biz, and baz, but if you run make SOME_VARIABLE=true it will only build foo and bar.
With the very generic, specifics-free question that's about all we can suggest.

Resources