Master Makefile for Subprojects Won't Compile Subprojects - makefile

I have a project that I am working to release that actually contains 3 subprojects, all of which need to be compiled in one go. My makefile looks roughly like this:
all: a b c
a:
#cd a && make
b:
#cd b && make
c:
#cd c && make
Projects A and B both compile fine but for the 3rd project, it tells me there is nothing to be done although switching to the C directory and running make does in fact compile code.
To be a little more specific: Project C in the example above is actually Mozilla's SpiderMonkey. Whereas A and B are code/makefiles that I have written, C is just a raw copy of SpiderMonkey from the Mozilla website. The actually compile command for it is:
make JS_DIST=/usr JS_THREADSAFE=1 JS_HAS_FILE_OBJECT=1
In my master Makefile, I have:
spidermonkey:
#cd spidermonkey/src && $(MAKE) JS_DIST=/usr JS_THREADSAFE=1 JS_HAS_FILE_OBJECT=1
Running "make spidermonkey" outputs "make: Nothing to be done for `spidermonkey'." How do I get make to run the command?
EDIT:
I've tried adding the following lines to my makefile:
.PHONY: spidermonkey
As well as renaming the spidermonkey rule to sm, but still no change.
EDIT:
My bad! I had spaces when I should have had a tab. doh!

You probably have a file or directory at the toplevel called "spidermonkey". Make thinks this is what its supposed to create, and since it is already there, make stops.
One of the most important rules to follow when writing makefiles is each target should create one file with the same name as the target. In other words, if you have
a:
<some command>
That command should produce a single file called "a".
Rules which do not produce files but are only there as placeholders are called phony targets, and they should be declared like this:
.PHONY: a
Make will then always assume that a has to be remade.
Also, as a general rule do not use "make" to invoke make recursively, use $(MAKE) instead.
EDIT: changed "pseudo" to "phony"

Make only checks for the existance of a file (or directory) named the same as the rule target, and if there is (and it is newer than the dependencies) then from make's point of view there is nothing more to do.
So your problem is that you have a spidermonkey rule (with no dependencies) as well as a directory called spidermonkey, and then make thinks "the target is already made, nothing for me to do". To get make to do what you want, rename the spidermonkey rule (or the directory).
Speaking of recursive make by the way, this is not neccessarily a good idea,
see Recursive Make Considered Harmful.

Related

Why "make all" works as expected without adding "all" to .PHONY target?

I know what a .PHONY does.
If in the folder where my Makefile is, I add an empty file called clean and after I run make clean all of the clean target will not be executed since there was not any change in the file, so the target will not run and this is correct.
If I add .PHONY: clean, than the clean is seen as a command and this is also correct.
My question is why this behavior does not happen the same to all target, since I added a all file in the folder.So basically the all target still executes like if it was a .PHONY: all
I have the fallowing makefile code.
all: test1 test2
test1: test1.o
test1.o: test1.c
test2: test2.o
test2.o: test2.c
clean:
rm -rf *.o test1 test2
How do you know that the all rule is "still executing"? That rule has no recipe, so there's no way it can be "executed".
If what you mean is that even though the all file exists in the local directory, make is still building the targets test1 and test2, that's how make works (this doesn't have anything to do with phony vs. non-phony targets). When make decides whether or not build a particular target first it tries to build all the prerequisites of that target, and all the prerequisites of those targets, etc. Only after all that is complete, can make know whether or not to build the first target (all in this case).
make clean here doesn't have any dependencies, so putting a file named clean there is enough for the target to be considered built.
make all on the other hand has dependencies. Even if you put a file named all there, Make has to check whether the all file is newer than test1 and test2. This process triggers builds of test1 and test2, and it happens to have the same effect as if all was a phony target.
The basis is that all: test1 test2 is a recipe for building a file named all, that depends on the files test1 and test2.
If you ran make all, Make would do something like this:
Analyse the Makefile.
Find out that all depends on test1 and test2.
Check the timestamp of all and see if it is "up to date".
It is "up to date" if none of the dependencies are newer than itself.
In other words, Make can skip building a file if it's newer than all it's dependencies.
Build outdated or missing files.
Now, if you would like to prevent Make from considering the targets as files, you could specify them as phony targets. That is best practice for non-file targets like all.
(This answer isn't disagreeing with either of the existing answers, but suggesting another way of thinking about this).
When you have a rule like
dst: src
action
you're saying two things (as you know):
if dst doesn't exist, or is older than src, then do action; and
when action completes, the file dst will exist.
With targets such as all or clean, the second statement is of course not true. Make doesn't hold you to the promise in (2), so when you say make all, it'll compute and generate the required dependencies, and not complain that there's no file all in place afterwards. You're lying to Make, but it doesn't mind (it's cool with that...). That is, this is basically a makefile hack.
Where this goes wrong, of course, is if for some reason there happens to be a file called all or clean. Then Make will take the modification date of the file all into account when calculating the dependencies, and possibly come to a conclusion you didn't expect.
So what .PHONY: all does is legitimise the hack, and tells Make ‘even if a file all exists, pretend that it doesn't’; you're basically cancelling promise (2).
Therefore, as the other answers state, mentioning .PHONY isn't necessary. It simply forestalls an error – easy to make but easy to miss – when a file matching a phony target is accidentally created.

Makefile pattern rules not working

I am learning makefiles, and can't just wrap my head around this problem i am having, and would like to understand how/why this fail.
I have half a dozen erlang files in a src directory. I want to compile these into a ebin directory, without having to define a rule for each and every one of them. According to the Gnu make documentation, pattern rules should be right up my alley.
However, with the following makefile, all I get from make is make: *** No targets. Stop. Why is that?
ebin/%.beam: src/%.erl
mkdir -p ebin
erlc -o ebin $<
Edit: Based on this answer, I now understand that i would have to explicitly declare the targets, for instance by using make ebin/cmplx.beam. However, i still do not understand how i should write my makefile to get my desired behaviour - since I have half a dozen targets (and in other projects even more), this seems like an unnecessary hassle. Is there not a way to define targets based on the source file names?
The target rule tells make that whenever it needs to produce a beam file in the ebin directory, and there exists a corresponding erl file in the src directory, it can use erlc.
However, this doesn't tell make that this is what it needs to do. You could explicitly tell make what it needs to do by giving it a target on the command line:
make ebin/foo.beam
If you don't give a target on the command line, make will pick the first non-pattern rule in the makefile as its target. However, your makefile doesn't have any non-pattern rules, so there is no target.
What you probably want is that for each existing erl file in src, make should consider the corresponding beam file in ebin to be a target. You can achieve that by calling wildcard and patsubst:
erl_files=$(wildcard src/*.erl)
beam_files=$(patsubst src/%.erl,ebin/%.beam,$(erl_files))
ebin/%.beam: src/%.erl
mkdir -p ebin
erlc -o ebin $<
all: $(beam_files)
(The indented lines need to be actual physical tabs, not spaces.)
That way, running make will rebuild all beam files that are out of date. all gets chosen as the default target, and it in turn depends on all beam existing or potential, each of which in turn depends on the corresponding erl file.
This trick is described in the GNU make manual.

make variables that depend on a target

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.

How do you run a command prior to including a component Makefile?

I am trying to create a subdirectory in my project (let's call it $PROJECT/child) that needs to pull in a Makefile (let's call it ../Makefile.inc) from its parent, $PROJECT/Makefile.inc. Later I want to copy $PROJECT/child somewhere else so it can run independently of $PROJECT.
There is a common Makefile that needs to be included in both projects and shipped when the subdirectory is copied, and I want it to be included in both cases. So I thought I would link it in during the child build, if it isn't found. (I don't want to just include ../Makefile.inc, because this will disappear when I copy the project, and I don't want the calling build system to be responsible for putting the Makefile.inc in place.)
With those constraints, here's a horrible hack that I've come up with to do this, within $PROJECT/child/Makefile:
HACK = $(shell test -f Makefile.inc || ln -f ../Makefile.inc .)
include $(HACK)Makefile.inc
Notice the extra special duct tape on that second command. I have to actually include $(HACK) even though it's going to end up empty, so that the $(shell ...) will be evaluated. ;-)
Is there a cleaner way to make this happen?
Give a rule to build Makefile.inc. (make will complain that Makefile.inc doesn't exist when it parses the include line, but it will go on parsing the main makefile, apply any rule to build included files, and go back and re-parse the main makefile with the included files.)
include Makefile.inc
Makefile.inc:
ln ../Makefile.inc $#

What does "all" stand for in a makefile?

I read some tutorials concerning Makefiles but for me it is still unclear for what the target "all" stands for and what it does.
Any ideas?
A build, as Makefile understands it, consists of a lot of targets. For example, to build a project you might need
Build file1.o out of file1.c
Build file2.o out of file2.c
Build file3.o out of file3.c
Build executable1 out of file1.o and file3.o
Build executable2 out of file2.o
If you implemented this workflow with makefile, you could make each of the targets separately. For example, if you wrote
make file1.o
it would only build that file, if necessary.
The name of all is not fixed. It's just a conventional name; all target denotes that if you invoke it, make will build all what's needed to make a complete build. This is usually a dummy target, which doesn't create any files, but merely depends on the other files. For the example above, building all necessary is building executables, the other files being pulled in as dependencies. So in the makefile it looks like this:
all: executable1 executable2
all target is usually the first in the makefile, since if you just write make in command line, without specifying the target, it will build the first target. And you expect it to be all.
all is usually also a .PHONY target. Learn more here.
The manual for GNU Make gives a clear definition for all in its list of standard targets.
If the author of the Makefile is following that convention then the target all should:
Compile the entire program, but not build documentation.
Be the the default target. As in running just make should do the same as make all.
To achieve 1 all is typically defined as a .PHONY target that depends on the executable(s) that form the entire program:
.PHONY : all
all : executable
To achieve 2 all should either be the first target defined in the make file or be assigned as the default goal:
.DEFAULT_GOAL := all
Not sure it stands for anything special. It's just a convention that you supply an 'all' rule, and generally it's used to list all the sub-targets needed to build the entire project, hence the name 'all'. The only thing special about it is that often times people will put it in as the first target in the makefile, which means that just typing 'make' alone will do the same thing as 'make all'.
The target "all" is an example of a dummy target - there is nothing on disk called "all". This means that when you do a "make all", make always thinks that it needs to build it, and so executes all the commands for that target. Those commands will typically be ones that build all the end-products that the makefile knows about, but it could do anything.
Other examples of dummy targets are "clean" and "install", and they work in the same way.
If you haven't read it yet, you should read the GNU Make Manual, which is also an excellent tutorial.

Resources