recursive makefile not building - c

I have a bunch of C files in different directories and I'm getting a make: nothing to be done for 'all' error with my recursive Makefile; however if I tweak the dependences I can get it to work... but I don't understand why I have to.
Here's my original Makefile:
APP_DIRS=rescoco ressys resvm
.PHONY: all
all: $(APP_DIRS)
$(APP_DIRS):
$(MAKE) --directory $#
clean:
$(RM) *~
Now if I change my line: .PHONY to .PHONY: all $(APP_DIRS) it builds fine.
Another possibility is if I change the line: $(APP_DIRS): to $(APP_DIRS): clean it builds fine.
(NOTE: removing .PHONY target doesn't change anything)
So what's going on here? Is the Makefile trying to tell me I haven't listed dependencies correctly? I was thinking make would do something like:
to build .PHONY I first have to build all
to build all I first have to build $(APP_DIRS)
$(APP_DIRS) has no prereqs so execute the command for that (which would cause the recursive makes to run).
Clearly I am wrong; but why?
FYI, if it matters my files are structured something like this:
Makefile #top level makefile as seen above
/rescoco
rescoco.c
Makefile #builds rescoco src and moves archive to ../lib directory
/ressys
ressys.c
Makefile #same as above but for ressys
/resvm
resvm.c
Makefile #same as above but for resvm
/lib
and my build command is simply make. When I run with make -n or make -n all I get no output at all:
:~/proj$ make -n all
make: Nothing to be done for 'all'.
:~/proj$

Things first you should be aware of:
If you have directories as dependencies, make is going to consider building the targets (i.e. executing the recipes for such directory targets), only if the modification timestamp of the directory gets updated.
This would happen only when you add a new file in the directory but not for file modifications in the directory. Adding files in a sub-directory does not change the timestamp of the directory.
PHONY targets are meant to be used when executing such a target does not create a file with the name of the target. In other words, you want make to execute the rule irrespective of whether the file already exists or not.
So your Makefile esentially only tells this:
To build the target all, I need to build $(APP_DIRS). Since all is a PHONY target, I will always execute the recipe for all.
$(APP_DIRS) is not a PHONY target and does not have any dependencies. So *only if $(APP_DIRS) does not exist already (i.e. the file or directory), I'm going to execute the recipe, otherwise I'm doing nothing for this target.
clean has no pre-requisite and not a PHONY, so I expect to execute this rule only when explicitly invoked by make (from the command line or another Makefile). Also clean is not a PHONY, so I expect the recipe to create a file called clean after execution (which is incorrect for your case)
Hence changing the .PHONY line to:
.PHONY: all $(APP_DIRS)
makes the Makefile go and execute the recipe for $(APP_DIRS) always.
So if you would like make to always traverse into all of the $(APP_DIRS) directories and invoke make again on them, you need to add $(APP_DIRS) to .PHONY, which makes $(APP_DIRS) a PHONY target, and executes the recipe irrespective of the file's/directory's timestamp if it exists.
For your particular use-case, I think this is the Makefile you should be using:
APP_DIRS=rescoco ressys resvm
.PHONY: all clean $(APP_DIRS)
all: $(APP_DIRS)
$(APP_DIRS):
$(MAKE) --directory $#
clean:
$(RM) *~
BONUS:
Changing $(APP_DIRS): to $(APP_DIRS): clean implies that $(APP_DIRS) depends on the clean target.
Although clean is not marked a PHONY, make does not see a file named clean in the current directory. So it goes ahead and tries to execute the recipe for clean.
Since a dependency of $(APP_DIRS) (i.e. clean) was built, this makes the Makefile execute the recipe for building $(APP_DIRS).
This brings us to an interesting observation:
- Any target that depends on a PHONY target will always get rebuilt (i.e. the recipe would be executed).
Take this simple Makefile:
all: target1
target1: target2
#echo "$#"
#touch $#
target2: target3
#echo "$#"
#touch $#
target3:
#echo "$#"
.PHONY: all target3
The first time I run make, I see this output:
target3
target2
target1
After this, files target1 and target2 are created. Even then, if I run make again, I would see the output:
target3
target2
target1
As you can see, the PHONY dependencies get propagated up and not the other way down. target2 gets rebuilt just because target3 is a PHONY, and target1 gets rebuilt just because target2 got rebuilt.

You are defining a variable named 'APP_DIRS' with a list of directories. That is fine.
You then do
$(APP_DIRS): make blah blah, which is essentially equivalent to rescoco ressys resvm: make blah blah
which obviously isnt valid.
So you need to pretend your $(APP_DIRS) is a variable, not a target name, which seems to be what you're using it as.
having said that, think why .PHONY: all $(APP_DIRS) works

This is how you can do it, just remove the wildcard if you don't want it.
make wildcard subdirectory targets

Related

Print output when executing public01, public02,

I have the following Makefile:
CC = gcc
CFLAGS = -ansi -Wall -g -O0 -Wwrite-strings -Wshadow \
-pedantic-errors -fstack-protector-all
PROGS = public01 public02 public03 public04 public05 public06 shell_jr
.PHONY: all clean
all: $(PROGS)
clean:
rm -f *.o $(PROGS) a.out
$(PROGS): shell_jr.c
public0%:
shell_jr < public0%.in > output
cat output
Whenever public0X is entered, the output of shell_jr.c when it is run with input coming from public0X.in should be displayed. The public0% tag is my attempt at making this happen. However, there are 3 problems. First, I can only have public0%.in as a dependency. That can be avoided by copy pasting separate commands for public01, public02, ... Second, when I do that and execute make, the command is immediately executed. How do I make sure that command is not executed until I type public01 and press enter?
First, I can only have public0%.in as a dependency.
I take this part to be asking about how to express in the recipe the correct name for the input file corresponding to the chosen target. The % of a pattern rule is expanded only in the target and prerequisites, not in the recipe, but in any make recipe, the automatic variable $# represents the complete target name being built. Since the wanted input name is formed by appending the suffix .in to the target name, it can be expressed as $#.in.
Additionally, you do not name the public0% targets as .PHONY (unlike clean and all), but your rule for them does not actually create them, either. If you are trying to both create and display these files, then you can also use $# to direct the output to the wanted file. Otherwise, you should mark these targets, too, as .PHONY.
Furthermore, if it your intention to (re)create these files regardless of whether anything has changed, then omitting the input files from the prerequisite list is appropriate. Otherwise, however, naming the input files as prerequisites will help make to skip needlessly regenerating the %public0% files.
Second, when I do that and execute make, the command is immediately executed. How do I make sure that command is not executed until I type public01 and press enter?
make is not interactive. If you want to specify a particular target or targets to build, instead of the default, then you express them as additional arguments on the make command line:
make public01
But I think what you're trying to get at may be a different problem than what you actually said. Your default target will build all of the targets named in $(PROGS), and where prerequisites do not require otherwise, GNU make running in serial mode will attempt to build the targets in the order in which they are named. Your public0% all depend on the shell_jr program, but they do not designate it as a prerequisite. (They do name shell_jr.c as a prerequisite, but that's not actually a direct dependency, and designating it as one does not serve a useful purpose.) Therefore, make will attempt to build all of the public0% targets before attempting to build shell_jr.
The correct thing to do here is to express the right dependencies. This version does that, on the assumption that the public0% are intended to be actual built files:
CC = gcc
CFLAGS = -ansi -Wall -g -O0 -Wwrite-strings -Wshadow \
-pedantic-errors -fstack-protector-all
PROGS = shell_jr
OUTPUTS = public01 public02 public03 public04 public05 public06
.PHONY: all clean
all: $(PROGS) $(OUTPUTS)
clean:
rm -f *.o $(PROGS) $(OUTPUTS)
# shell_jr is built according to a built-in rule (as was already the case)
public0%: public0%.in shell_jr
shell_jr < $#.in > $#
cat $#
Note that this will rebuild (and display) the public0% files only if their corresponding input files have changed or if shell_jr needed to be rebuilt. If you want them to be built and displayed even when nothing has changed then you can add a target with no prerequisites or recipe, and make it a prerequisite for the public0% rule:
public0%: public0%.in shell_jr FORCE
shell_jr < $#.in > $#
cat $#
FORCE:
.PHONY: FORCE
The FORCE target will be considered to have been rebuilt every time make runs, thus triggering the public0% targets to be rebuilt.

Make: compile object file twice in the same target

I have the following simple problem in a Makefile:
%.o:: %.c
gcc -o $# -c $<
lib1.a: test.o
ar -r $# test.o
rm *.o
lib2.a: test.o
ar -r $# test.o
rm *.o
all: lib1.a lib2.a
make lib1.a or make lib2.a work properly. However, make all gives:
gcc -o test.o -c test.c
ar -r lib1.a test.o
rm *.o
ar -r lib2.a test.o
ar: test.o: No such file or directory
make: *** [lib2.a] Error 1
I need to do the rm *.o cause I want the object file to compile each time (in my real Makefile, I have a more complex use case where I compile with different flags).
How can I fix this problem? It seems that make compiles the object file only once.
I tried with .PHONY instead of doing the rm, but again, it compiles only once.
Your makefile is a bit against the make logic, this is why the result is not what you expect:
Here you define two targets (lib1.a and lib2.a) with a common dependency: test.o.
Then you define the rule all (which, by the way, should be .PHONY but this isn't a problem here) that depends on lib1.a and lib2.a.
So, in order to "do" all, make have to build lib1.a and lib2.a. They both depend on test.o, so make builds test.o once, then build lib1.a and lib2.a, expecting that the recipes you defined will just build those files, and nothing more.
The problem is that you delete test.o in the recipe for lib1.a and lib2.a, although this action is not needed to build them, this is something you want to do when cleaning, not building.
There are two solutions:
Move the deletion operation in a rule that is meant to do that (a .PHONY rule named clean for example).
The use of intermediate targets which will be deleted when they're not needed anymore. In fact, you can achieve that without even thinking about intermediate targets if you simply delete the first rule of your makefile (the %.o:: %.c one), because make already has an implicit rule that does that using intermediate targets.
Make is a rule-based system. Rules are declarative: you declare what you want built from what, you don't specify the order in which this happens (unless you can't avoid it). So a good Makefile is declarative: all results are declared like in a declarative programming language. They are like final variables in Java: you bind them to a value, you don't reassign them to a different value afterwards.
Make is also file-based: its "variables", targets and prerequisites are files.
So if you want to build two different things, don't call them by the same name! If you want two different test.o files, call them differently. The problem will go away without you needing to try and convince make that it should be like an imperative programming language, which it was specifically designed not to be. If you want an imperative build specification, use a shell script.

Writing Makefile in C

I am writing(at first time) a makefile for my program in C. This is my make file:
CC = gcc
FILES = in_one.c in_two.c in_two.h
OUT_EXE = out_executable
build: $(FILES)
$(CC) -o $(OUT_EXE) $(FILES)
clean:
rm -f *.o core
rebuild: clean build
Actually, everything works properly : Gcc compiler doesn't show any errors, but maybe someone could explain what does these lines mean:
clean:
rm -f *.o core
rebuild: clean build
The clean lines say that if you want to make clean it does not depend on anything (nothing behind ":"). Furthermore the rm command deletes all object files.
The rebuild: clean build says that if you want to make rebuild it depends on clean and build. So the first thing to do is clean (= delete all object files) and then make build (= compile all source files). After that there is nothing more to do so make stops.
For a quick start, make recipes have the following syntax:
target: dependency1 dependency2 ... dependencyN
command1
command2
...
command3
So if target needs to be made at first all dependencies (dependency1 - dependencyN) are made. After this is done command1 - commandN are executed in that order.
You are rm (removing) or deleting all (*) the existing .o Files. So the next time you compile or call the make file you are just left with the new ones.
Build: $(Files) is creating the .o so the compiler can link them together into an executable

Makefile with multiple submodules

I have following program structure:
main.c
Makefile
Submodule
--{somefiles}
--Makefile
Submodule is creating library submodule.a. It has many source files and it need some libraries.
All I want to know that
Makefile in submodule knows how to make submodule.a
Makefile in submodule sets variable SUBMODULE_LDFLAGS and SUBMODULE_LDLIBS
How can I write Makefile in root project directory that:
it would create submodule.a using Makefile in submodule
it would add SUBMODULE_LDFLAGS and SUBMODULE_LDLIBS to its own variable?
AT the end I want the following command in main Makefile works correctly:
TARGET = MyProgram
OBJS = $(TARGET).o submodule/submodule.a
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $# $(LDLIBS)
Now it creates MyProgram.o and cannot create MyProgram, because Makefile doesn't know how to make submodule/submodule.a.
I can add lines:
submodule/submodule.a:
make -C submodule
but it won't help me with missing libraries.
There is no direct way for the sub-Make to pass variables to the parent process. There are (at least) two indirect ways.
You could have the sub-Make write a file containing the variable values, which the parent Make could then read.
You could copy the part of submodule/Makefile that constructs those variables, and put it into Makefile. Better still, you could isolate that code in a separate file that both makefiles would then include.
EDIT:
One disadvantage of recursive Make is that it interrupts much of Make's dependency handling. In this case, there's no clean way to have the sub-make run when and only when one of the library's sources is changed.
You can put the list of submodule sources -- or the code that constructs the list -- in a separate file which both makefiles will include. Then those files can be among the prerequisites of $(TARGET).
Or, you could make submodule/submodule.a a PHONY target. In that case, Make will rebuild the binary every time, but otherwise it'll work perfectly.

make: Nothing to be done for `all'

I am going through an eg pgm to create a make file.
http://mrbook.org/tutorials/make/
My folder eg_make_creation contains the following files,
desktop:~/eg_make_creation$ ls
factorial.c functions.h hello hello.c main.c Makefile
Makefile
# I am a comment, and I want to say that the variable CC will be
# the compiler to use.
CC=gcc
# Hwy!, I am comment no.2. I want to say that CFLAGS will be the
#options I'll pass to the compiler
CFLAGS=-c -Wall
all:hello
hello:main.o factorial.o hello.o
$(CC) main.o factorial.o hello.o -o hello
main.o:main.c
$(CC) $(CFLAGS) main.c
factorial.o:factorial.c
$(CC) $(CFLAGS) factorial.c
hello.o:hello.c
$(CC) $(CFLAGS) hello.c
clean:
rm -rf *o hello
error:
desktop:~/eg_make_creation$ make all
make: Nothing to be done for `all'.
Please help me understand to compile this program.
Sometimes "Nothing to be done for all" error can be caused by spaces before command in makefile rule instead of tab. Please ensure that you use tabs instead of spaces inside of your rules.
all:
<\t>$(CC) $(CFLAGS) ...
instead of
all:
$(CC) $(CFLAGS) ...
Please see the GNU make manual for the rule syntax description: https://www.gnu.org/software/make/manual/make.html#Rule-Syntax
Remove the hello file from your folder and try again.
The all target depends on the hello target. The hello target first tries to find the corresponding file in the filesystem. If it finds it and it is up to date with the dependent files—there is nothing to do.
When you just give make, it makes the first rule in your makefile, i.e "all". You have specified that "all" depends on "hello", which depends on main.o, factorial.o and hello.o. So 'make' tries to see if those files are present.
If they are present, 'make' sees if their dependencies, e.g. main.o has a dependency main.c, have changed. If they have changed, make rebuilds them, else skips the rule. Similarly it recursively goes on building the files that have changed and finally runs the top most command, "all" in your case to give you a executable, 'hello' in your case.
If they are not present, make blindly builds everything under the rule.
Coming to your problem, it isn't an error but 'make' is saying that every dependency in your makefile is up to date and it doesn't need to make anything!
Make is behaving correctly. hello already exists and is not older than the .c files, and therefore there is no more work to be done. There are four scenarios in which make will need to (re)build:
If you modify one of your .c files, then it will be newer than hello, and then it will have to rebuild when you run make.
If you delete hello, then it will obviously have to rebuild it
You can force make to rebuild everything with the -B option. make -B all
make clean all will delete hello and require a rebuild. (I suggest you look at #Mat's comment about rm -f *.o hello
I think you missed a tab in 9th line.
The line following all:hello must be a blank tab. Make sure that you have a blank tab in 9th line. It will make the interpreter understand that you want to use default recipe for makefile.
That is not an error; the make command in unix works based on the timestamps. I.e let's say if you have made certain changes to factorial.cpp and compile using make then make shows
the information that only the cc -o factorial.cpp command is executed. Next time if you execute the same command i.e make without making any changes to any file with .cpp extension the compiler says that the output file is up to date. The compiler gives this information until we make certain changes to any file.cpp.
The advantage of the makefile is that it reduces the recompiling time by compiling the only files that are modified and by using the object (.o) files of the unmodified files directly.
Using the comment from Paul R, I found that
make clean
followed by
make
or
make all
fixed my problem.
I arrived at this peculiar, hard-to-debug error through a different route. My trouble ended up being that I was using a pattern rule in a build step when the target and the dependency were located in distinct directories. Something like this:
foo/apple.o: bar/apple.c $(FOODEPS)
%.o: %.c
$(CC) $< -o $#
I had several dependencies set up this way, and was trying to use one pattern recipe for them all. Clearly, a single substitution for "%" isn't going to work here. I made explicit rules for each dependency, and I found myself back among the puppies and unicorns!
foo/apple.o: bar/apple.c $(FOODEPS)
$(CC) $< -o $#
Hope this helps someone!
I was trying to install libuv on Ubuntu and i also got the error make: Nothing to be done for 'all'. As i see it, using make gives two ways to solve the problem, one for check and one for install. But i found a workaround
still use the sudo make check command - it helps to read all the error messages before deciding on further actions. Basically, i've introduced a regression that makes the update workaround inefficient. This error comes from make however, the workaround from install fixes this, just try to run sudo make install and see what happens.
The make command will be a local optimization at the expense of the overall result of check/install - c'est ma façon de parler.
I believe i have narrowed down the problem considerably: in the first case after check i have "FAIL: test/run-tests" and in the second after install i get "specify the full pathname of the library, or use the '-LLIBDIR'" This argument to check/install can be a list object to store information about completed installations.
So install reports partial success when nothing actually happened.
Try running the commands from root:
cd your_program
sh autogen.sh
./configure
make
make check
make install
And then he writes that the installation was successful:
Libraries have been installed in:
/usr/local/lib
In your case, I strongly feel the only and simple problem you had is that you only preprocessed your app. You did so by having the flag -c under CFLAGS.

Resources