I am trying to build release and debug version of my binary. all is building the release, which is working alright. I would like to add a make debug to change my binary name and compile with a set of different flags. To do this, I'm using target specific variables in my top Makefile.
BINARY=hello
debug: DBG:=1
debug: $(BINARY)+=_debug
export DBG
debug: bin/$(BINARY).bin
all: bin/$(BINARY).bin
$(BINARY).bin has its own set of rules which work fine for the release part, as it was the only target I had before. After adding the debug target, I was hoping,
The DBG variable gets exported, so that my recursive Makefile can pick it up to change compilation flags, which I think is working
The binary name changes, appending _debug which it is not. Not sure what I'm doing incorrectly.
EDIT:
Adding some more information about how my bin target is built. My bin/$(BINARY).bin target depends on some .img and other .bin files whose target name I would also like to change based on whether I am building release or debug.
bin/$(BINARY).bin: bin/$(SOME_IMAGE).img bin/$(BINARY_1).bin
.....
bin/$(SOME_IMAGE).img: bin/$(BINARY_2).bin
......
bin/$(BINARY_1).bin: bin/$(BINARY_1).hex
......
bin/$(BINARY_1).hex:
$(MAKE) -C some-dir
bin/$(BINARY_2).bin: bin/$(BINARY_2).hex
......
bin/$(BINARY_2).hex:
$(MAKE) -C some-other-dir
to build debug, I am trying:
debug: export DBG:=1
debug: $(BINARY)+=_debug
debug: $(SOME_IMG)+=_debug
debug: $(BINARY_1)+=_debug
debug: $(BINARY_2)+=_debug
but that isn't doing the trick
This is roughly how I would approach the problem:
BINARY=hello
all: bin/$(BINARY).bin
debug: DBG:=1
debug: bin/$(BINARY)_debug.bin
bin/$(BINARY).bin bin/$(BINARY)_debug.bin:
#echo building $#, flag is $(DBG)
I am not sure that this solves your whole problem-- I couldn't parse your first bullet point. If it doesn't, perhaps you could edit your question to add a complete example.
The value of target-specific variable is available only within the target's recipe, not for the target's prerequisites. When you create the target-specific variable by incrementing the global variable, you now have two variables, one global, one target-specific. Yes you can export target-specific variable to prerequisites in a submake, with an export attribute. (All of this comes from the manual, section on target-specific variables.).
Prerequisites are evaluated at parse-time, from the current values of global variables (not from target-specific ones).
So, this is what you probably want. You seem to prefer trial-and-error, to actually RTFM. IMHO, you should really RTFM more, not guess functionality.
BINARY:=hello
all: bin/$(BINARY).bin
BINARY := $(BINARY)_debug
debug: export DBG:=1
debug: bin/$(BINARY).bin
If this "does not work", here is how you post questions on Stack Overflow.
You have a programming goal in mind and you write some code and it does not work the way you expect.
You make the code smaller and smaller to search for the cause of the problem.
If you have the smallest amount of code that reproduces the problem, and you still don't understand why your code does not work, then you post the complete minimal code in your question, and all details of your expectation, and your results different than the expectation.
Related
This requirement is a pre run requisite to a bigger make system.
I cannot/ do not wish to change the system make, hence the need to have the output from this make have a single target. Whilst I have many years of programming , I am a novice with regard to makefiles. So any help is greatly appreciated. Now on with the problem.
Firstly I don't want the the target being built if no inputs change. Exactly what a standard makefile is all about.
The problem I am having is getting the target built when the inputs do change. The inputs are comprised of EITHER an environment variable OR a couple of files. NOTE The Environment variable is set outside the makefile.
Here are the scenarios.
1 Enviroment variable and files not changed. Target not built.
2 Enviroment variable not changed. Files changed. Target built.
3 Enviroment variable changed. Files not changed. Target built.
4 Enviroment variable changed. Files changed. Target built.
The problem I'm having is number 3. How do I get the target to build when only the Environment variable changes from its previous setting. NOTE There is no problem in having the system maintain a file or setting containing the previous environment variable value to track the change
Since you didn't provide your existing makefile attempt or give any details about which variables you care about, I'll just show how to write a "check env vars" recipe and leave it to you to embed it into your makefile.
Make deals with files, and the only kind of comparison it can make is file timestamps. So, all prerequisite decisions must be expressed in terms of files and timestamps.
You can do this:
result: check-env.out $(SOMEFILES)
touch $#
check-env.out : FORCE
echo "$$SOMEVAR" > $#.new
test -f '$#' && cmp -s '$#'.new '$#' \
&& rm -f '$#'.new \
|| mv -f '$#'.new '$#'
FORCE:
The FORCE prerequisite is used to ensure that the check-env.out recipe always runs. However, it's only updated if the variable contents change, so the target that depends on it (result in this case) won't be updated due to this target if it hasn't changed.
I have a Variable in make that is dependant on a file that must be built before the variable can be set, is there a way to get this to work?
parsable_file: dependancies
commands to make parsable_file
targets=$(shell parse_cmd parsable_file)
$(targets): parsable_file
command to make targets
.phony: all
all:$(targets)
If I run $ make parsable_file && make all this will work (I get an error that parse_cmd cant find parsable_file but it works), but just make all will not work. Is there a Make idiom for this?
Set the variable in a file that you include in the main makefile and include a rule in the main makefile for how to build it (the one you already have should be fine).
I believe that will do what you want.
See Including Other Makefiles and How Makefiles Are Remade (which is linked from the first section) for more details on this concept.
Also, unless parseable_file has a usage independent from that parse_cmd call, it should be possible to do the creation and the parsing at the same time and just have the resulting makefile contain the correct value for $(targets) in one step.
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...
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: $^
Most Linux apps are compiled with:
make
make install clean
As I understand it, the make command takes names of build targets as arguments. So for example install is usually a target that copies some files to standard locations, and clean is a target that removes temporary files.
But what target will make build if no arguments are specified (e.g. the first command in my example)?
By default, it begins by processing the first target that does not begin with a . aka the default goal; to do that, it may have to process other targets - specifically, ones the first target depends on.
The GNU Make Manual covers all this stuff, and is a surprisingly easy and informative read.
To save others a few seconds, and to save them from having to read the manual, here's the short answer. Add this to the top of your make file:
.DEFAULT_GOAL := mytarget
mytarget will now be the target that is run if "make" is executed and no target is specified.
If you have an older version of make (<= 3.80), this won't work. If this is the case, then you can do what anon mentions, simply add this to the top of your make file:
.PHONY: default
default: mytarget ;
References:
https://www.gnu.org/software/make/manual/html_node/How-Make-Works.html
GNU Make also allows you to specify the default make target using a special variable called .DEFAULT_GOAL. You can even unset this variable in the middle of the Makefile, causing the next target in the file to become the default target.
Ref: The Gnu Make manual - Special Variables
bmake's equivalent of GNU Make's .DEFAULT_GOAL is .MAIN:
$ cat Makefile
.MAIN: foo
all:
#echo all
foo:
#echo foo
$ bmake
foo
See the bmake(1) manual page.