How can i set a debug variable when building target in makefile.
I want to set a debug_flag variable true only when I am building the target using make target.
You can use the below Makefile:
debug_flag=false
#here VAR is assigned with the value true only when you build target.
target: debug_flag=true
target:
echo $(debug_flag)
Related
I was experimenting with Makefiles, specifically with Makefile rules containing more than one target
Consider this Makefile:
x := $(MAKECMDGOALS)
y := Whatever
dummy $(y) $(x) :
#echo target: $#
Here, a simple make invocation outputs target: dummy, but a make xyz outputs target: xyz. Why does this happen? Is there something special with the MAKECMDGOALS variable? Why is variable x being treated 'with more importance' compared to y?
Why would it have anything to do with MAKECMDGOALS? It's just normal behavior.
Run this makefile, which doesn't use MAKECMDGOALS or variables at all, and you'll see the same result:
dummy Whatever xyz:
#echo target: $#
It's because the default target for make if you don't give any goals on the command line is the first one, which in this case is dummy. If you do give a goal (such as make xyz) then that's the target that will be built.
I am facing the issue while accessing a variable from other makefile which is included.
i have test.mak which has variable LIBS32 := $(TESTLIBS)/$(NEW_PLAT32)
i have included test.mak in other makefile and trying to assign that variable in one of the target.
extlib32: EXTLIBS = $(LIBS32)
extlib64: EXTLIBS = $(LIBS64)
The expected value of EXTLIBS should be '/home/testlib/extlibs/Linux' . But here when i print EXTLIBS the value which i am seeing is '/home/testlib/extlibs/'
Note:- When i jut print LIBS i can see the content as expected. But when i assigned to EXTLIBS and try to use it.. I can see word 'Linux' is missing.
Thanks!
You set EXTLIBS as a target-specific variable for target extlib32. Such variables are non-global and their value is only available in the target recipe and target's prerequisites, rather than globally (this is why $(info $(EXTLIBS)) doesn't print the expected value).
To print its value you need to print it from the recipe of target extlib32, e.g.:
extlib32:
#echo "EXTLIBS=${EXTLIBS}"
If extlib32 and extlib64 are .PHONY targets to build something then your original target-specific assignments should propagate to the dependencies and be available in their recipes. You just cannot print its value from the global makefile scope.
To have one makefile build both in 32 and 64-bit mode (as well as release and debug) you need to structure it differently and invoke make separately for each build mode. Example:
# User can overrided capitalized variables. E.g.
# make BUILD=release MODE=32 LDLIBS=-lrt
BUILD := debug
MODE := 64
build_dir := ${BUILD}/${MODE}
ldlibs.32 := my-32-bit-libs
ldlibs.64 := my-64-bit-libs
ldlibs := ${ldlibs.${MODE}} ${LDLIBS}
all :
#echo "build_dir=${build_dir}"
#echo "ldlibs=${ldlibs}"
Usage examples:
$ make
build_dir=debug/64
ldlibs=my-64-bit-libs
$ make BUILD=release MODE=32
build_dir=release/32
ldlibs=my-32-bit-libs
Another example for debug/release compiler options.
I would like to have something like that:
PrintTarget:
#echo Building $(TARGET)
SetRelTarget: TARGET = Release
SetRelTarget:
#echo Target is set.
BuildRel: SetRelTarget PrintTarget
But TARGET variable set in SetRelTargetAs is not a global.
My question is:
Is it possible to modify global variables inside the rule and use this modified value outside this rule?
Thank you.
Set TARGET to release in BuildRel, then it should apply to all its prerequisites (although it's not global),
PrintTarget:
#echo Building $(TARGET)
#SetRelTarget: TARGET = Release
SetRelTarget:
#echo Target is set to $(TARGET).
BuildRel: TARGET = Release
BuildRel: SetRelTarget PrintTarget
Since there is nothing variable in the code you can simply do this:
TARGET = Release
PrintTarget:
#echo Building $(TARGET)
BuildRel: PrintTarget
Demo:
$ make BuildRel
Building Release
$ make TARGET=foo BuildRel
Building foo
If your use case is more complex please include more details.
Is there a way to use the native Makefile if-else conditional and also have it respects target-specific variables re-assignments?
Example Makefile:
#!/usr/bin/make
CONFIG = Debug
.PHONY: test printme
test: override CONFIG=Release
test: printme
#echo "Done."
printme:
ifeq "$(CONFIG)" "Debug"
#echo "should be DEBUG -> $(CONFIG)"
else
#echo "should be RELEASE -> $(CONFIG)"
endif
Running make test prints the following output:
should be DEBUG -> Release
Done.
The output I'm looking for is should be RELEASE -> Release how can I achieve that? Do I need to use shell conditionals instead?
This behavior seems logical to me: At the time of parsing the Makefile, CONFIG is defined as Debug. The ifeq conditional uses the value of CONFIG it knows at that time. Therefore it chooses the ifeq branch that outputs "Should be DEBUG".
The target-specific variable is only defined as Release with the target test. Its prerequisite printme also knows the target-specific variable and ouputs Release.
May I suggest that you set variable to make on the command line for the purpose you want. It's not many more characters to write when invoking make but brings all you seem to be willing.
make CONFIG=Release
if I run make like this:
make VAR=dir
is there a way to add the location pointed by the VAR variable as a target dependency? actually, I need to define a file inside that directory as a dependency.
I'd go with:
target: $(VAR)/file.txt
echo yes
but if the variable was not defined, the target will understand /file.txt, which is not what I want. I also thought about creating a phony target to check for the variable, with test, but then the phony target would be executed every time and, consequently, target also would.
any solution to that?
You haven't said what behavior you want if the variable is not defined, but this is probably what you want:
ifdef VAR
target: $(VAR)/file.txt
endif
target:
echo yes
#echo and here are the dependencies: $^