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

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.

Related

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

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

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

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

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.

How to move qt4_wrap_cpp output to a folder?

I have made a call to qt4_wrap_cpp(moc_outfiles ${moc_header}) and I want the results of that call (moc_outfiles) to be placed in a folder called GeneratedFiles/Debug.
So far what I tried to make my own custom method that failed due to parsing error Parse error. Expected "(", got quoted argument with text "${it}".
FOREACH (it ${moc_headers})
QT_MOC_EXECUTABLE ${it} -o ./GeneratedFiles/Debug/moc_"${it}"
ENDFOREACH(it)
It looks like you need the execute_process command. Also, you probably don't want the quotes round ${it} in your output filename:
FOREACH(it ${moc_headers})
EXECUTE_PROCESS(COMMAND ${QT_MOC_EXECUTABLE} ${it} -o ./GeneratedFiles/Debug/moc_${it})
ENDFOREACH(it)
You may need to add the WORKING_DIRECTORY argument too - I'm unfamiliar with Qt's moc exe.
Instead of using qt4_wrap_cpp you could use the qt4_generate_moc macro, which takes a single file to be moced and an output path. With this macro you can construct something similar to what qt4_wrap_cpp does.
#qt4_wrap_cpp( moc_outfiles ${moc_headers} )
foreach(moc_hdr ${moc_headers})
GET_FILENAME_COMPONENT(moc_name ${moc_hdr} NAME_WE)
SET (moc_out ${PROJECT_SOURCE_DIR}/GeneratedFiles/moc_${moc_name}.cxx)
QT4_GENERATE_MOC( ${moc_in} ${moc_out} )
LIST (APPEND MOC_SOURCES ${moc_out})
endforeach(moc_hdr)

Resources