Makefile calling other makefile with target, gives wrong target - makefile

I have a makefile with a target clean:
clean:
$(MAKE) -f <other makefile location> clean
When I call make clean in this makefile, it tells me that in the other makefile there is no rule 'clean-linux'. Specifically here is the output.
make -f /root/ovaldi-5.5.25-src/project/linux/Makefile clean
make[1]: Entering directory '/root/ovaldi-5.5.25-src'
make[2]: Entering directory '/root/ovaldi-5.5.25-src'
make[2]: *** No rule to make target 'clean-linux'. Stop.
make[2]: Leaving directory '/root/ovaldi-5.5.25-src'
make[1]: Leaving directory '/root/ovaldi-5.5.25-src'
Why is it giving it the clean-linux target and not just clean like I specified?

When you make (or $(MAKE)), by default you use whatever makefile is there. So here's what I think is happening.
You cd to some location.
You 'make -f Makefile_A clean'.
make runs with Makefile_A, and does '$(MAKE) -f Makefile_B clean'.
make[1] runs with Makefile_B, and does '$(MAKE) clean-linux'.
make[2] runs with whatever makefile is here which might be anything (I suspect it's Makefile_A) but whatever it is it has no rule for clean-linux.
The solution: rewrite your second makefile (the one that has clean-linux) so that clean-linux becomes a prerequisite of clean (if/when you're on a linux system). That way it won't run make[2].
ifeq ($(PLATFORM), LINUX)
clean: clean-linux
endif
ifeq ($(PLATFORM), SUNOS)
clean: clean-sunos
endif
clean:;

Just a guess but maybe the 'clean' target in the second makefile calls 'clean-linux'?
Can you post the clean target of the second makefile?
Edit:
In light of your posted clean target it seems you're just calling the clean-linux target incorrectly.
Beta has posted the correct way of dealing with your problem in their answer so I'm going to +1 that.

Related

How to let Makefile see target from another file

I have such Makefile with a content for creating a script:
.PHONY cluster-run
cluster-run:
make $(TARGET) --just-print >> tmp_script.sh;
And another one nn.mk:
.PHONY nn-model
include Makefile
nn-model:
python run-nn.py
I have two separate Makefiles for readability, because their content is big and I have another '*.mk' files, like nn-lstm.mk, nn-conv.mk, etc.
I launch as follows:
make -f nn.mk cluster-run TARGET=nn-model
But make gives an error:
make nn-model --just-print >> tmp_script.sh;
make[1]: *** No rule to make target `nn-model'. Stop.
make: *** [cluster-run] Error 2
For me such behaviour is strange because target nn-model actually exists. How can I fix this problem?
First you should never use raw make in recipes. Always use the $(MAKE) variable.
Second, the problem is because when you run the sub-make you don't provide the -f option:
make nn-model --just-print >> tmp_script.sh;
Because of that, it reads Makefile but not nn.mk, and so there's no rule to build the target nn-model.
Remember if you run a sub-make like this it's starting an entirely new make process with a clean slate: none of the targets defined in the parent make process are known to the sub-make when it starts.
I don't know what you mean by target nn_model actually exists but there's definitely no file named nn_model or you wouldn't get that error.
So what's happening is that when you build cluster-run it invokes a recursive make, which reads Makefile, and asks it to build $(TARGET) (which will include nn-model).
Notice that the recursive make is a new make and does not inherit variables or rules from the parent make, so this make instance has no clue how to build nn-model If you want the child make to see this, then the child make must include the parent one...

gcc - What does ../ (dot dot slash) mean in a variable in a Makefile?

I have searched for hours for an answer to this. I am new to gcc and Makefiles.
I have a Makefile in some source code that looks like this:
CC=gcc
SRCDIR=src
BINDIR=../bin
CFLAGS= -flag
LIBS= -lthing
...
$(BINDIR)/program_name: $(SRCDIR)/program_name.c
$(CC) $(CFLAGS) $(SRCDIR)/program_name.c -o $(BINDIR)/program_name $(LIBS)
I understand what all of this means except what ../ in BINDIR is meant to do. When I make the Makefile, I get the error message:
/usr/bin/ld: cannot open output file ../bin/program_name: No such file or directory
collect2: error: ld returned 1 exit status
Makefile:20: recipe for target '../bin/program_name' failed
make: *** [../bin/program_name] Error 1
My guess is that the original author of this Makefile meant that the bin folder should go in the parent directory of where the Makefile is located. I know when using the Linux CLI command cd that the dot dot means go up a directory. Is that what this is trying to achieve?
To automatically create the $(BINDIR) directory before it is actually needed you must declare it as a prerequisite (dependence) of any target that uses it. But each time its content changes its timestamp also changes. So, declaring it as a regular prerequisite is not the best thing to do because the targets depending on it would be re-built without real reason, just because the content of $(BINDIR) changed.
This is why make also supports order-only prerequisites (OOPs):
$(BINDIR)/program_name: $(SRCDIR)/program_name.c | $(BINDIR)
$(CC) $(CFLAGS) $< -o $# $(LIBS)
$(BINDIR):
mkdir -p $#
Note the | that introduces the list of OOPs. An OOP is built if it does not exist, which causes the targets depending on it to be (re-)built too. But if it exists make does not even consider its last modification time. Even if some target depending on it is older, it is not rebuilt just because of that.
Note: I also used the $< and $# automatic variables. In the rule's recipe they expand as the first prerequisite ($(SRCDIR)/program_name.c) and the target ($(BINDIR)/program_name), respectively. They are highly recommended: less typing, less errors prone, more generic rules... they have many good properties.
Your makefile is missing a rule to create the BINDIR directory - if it doesn't exist, your link line won't be able to put the resulting binary there! A rule like this one should do it:
$(BINDIR):
mkdir -p $(BINDIR)
Just make sure that any other rules (like the one in your question) also depend on this directory!

makefile - make: *** No rule to make target all'. Stop

i have been trying to make a correct makefile for a while now but i keep getting the error "make: *** No rule to make target `all'. Stop."
i have one main program: mpasswdsort.c
and the c file wich is used by mpasswdsort, it comes with a header as well:
list.c and list.h
my makefile:
CC=gcc
CFLAGS=-Wall -pedantic -ansi
all: mpasswdsort
server: mpasswdsort.o list.o
$(CC) mpasswdsort.o list.o -o mpasswdsort
mpasswdsort.o: mpasswdsort.cpp
$(CC) $(CFLAGS) mpasswdsort.cpp
list.o: list.cpp
$(CC) $(CFLAGS) list.cpp
clean:
rm -f server client *.o core
I am unsure if its wrong in the makefile or if the makefil isnt supposed to be a .txt file.
The error message you present indicates that make does not see any rule for building target "all". It is exactly the same diagnostic that GNU make emits when there is no makefile at all. Since the makefile contents you present do contain a rule for target "all", I conclude that make is not seeing them.
That may be because the makefile is in a different directory, because its name is different from the ones make tries by default (Makefile or makefile is conventional; GNU's version of make also checks for GNUmakefile), or because an access-control issue prevents make from reading the file. Since you remark
I am unsure if its wrong in the makefile or if the makefil isnt
supposed to be a .txt file.
, the most likely conclusion is that (at least) the filename is wrong. Makefiles are text files, but text file names don't necessarily end with ".txt". In fact, on Linux and other UNIXes, most of them don't. Makefiles shouldn't have such an extension, though, technically, you can use the -f option to tell make the name of the makefile to use.
For me, quite simply, I was initiating the make init command outside of the target directory that I wished to create the makefile. Hope this helps someone.
I'm using a MAC so renaming the "MakeFile" to "Makefile" did the trick for me.
And one more thing, I got this error after fixing the previous one:
Makefile:3: *** missing separator. Stop.
Replacing the four spaces with tabs solved this problem for me! Simply just delete the space before the commands in your "Makefile" and put a tab behind them.

How to make a target in make that is itself named 'makefile'?

Summary: I'm dealing with a make script that generates (and optionally 'makes') a makefile. Historically it used a make make "phony target" to do so. I want to change this to make makefile because it seems more coherent and representative of what's going on. But when I change it and switch to the .FORCE idiom so it will be generated dependent on an artificial phony target, it seems the makefile is created 4 extra times for a reason I do not understand.
Details: The way the script works is that you can write either:
make -f makefile.boot
or:
make -f makefile.boot make
In the first case, it assumes you want to use the rules in makefile.boot to generate a platform-specific makefile, and then run make on that file. In the second case it assumes you only want to create the makefile but not execute it.
Here is a stripped down version of makefile.boot in make make terms that works:
top: make
$(MAKE)
make:
#echo "Pretending to generate makefile..."
cp makefile.fake makefile
The makefile we "generate" wants to be a superset of makefile.boot. It wants to be able to do the make make generation process as well, but its top target is an actual build. So makefile.fake contains
top: product
make:
#echo "Pretending to generate makefile..."
cp makefile.fake makefile
product:
#echo "Pretending to make build product..."
echo "Build Product" >> product
It works, but I had a thought:
"make make" is confusing to read, and it would be clearer if it was "make makefile" instead
An immediate problem with that is when you have a real target instead of a phony one, then if the file exists and has no dependencies it won't get rebuilt. I wanted this makefile to be created every time you did make makefile or make -f makefile.boot makefile. So I used the .FORCE idiom to depend on a phony target. Updated makefile.boot:
.FORCE
top: makefile
$(MAKE)
makefile: .FORCE
#echo "Pretending to generate makefile..."
cp makefile.fake makefile
And an updated makefile.fake:
.FORCE:
top: product
makefile: .FORCE
#echo "Pretending to generate makefile..."
cp makefile.fake makefile
product:
#echo "Pretending to make build product..."
echo "Build Product" >> product
Which seems all well and good, but it now runs the makefile generation five times:
/test$ make -f makefile.boot
Pretending to generate makefile...
cp makefile.fake makefile
make
make[1]: Entering directory '/test'
Pretending to generate makefile...
cp makefile.fake makefile
Pretending to generate makefile...
cp makefile.fake makefile
Pretending to generate makefile...
cp makefile.fake makefile
Pretending to generate makefile...
cp makefile.fake makefile
Pretending to make build product...
echo "Build Product" >> product
make[1]: Leaving directory '/test'
The first one I want, and seems like the only one I asked for. Where are all the other calls coming from? What's triggering the four additional requests for makefile? Or in the absence of understanding, is there an alternative way of achieving my intent?
Do recall that makefile is a magic target in many make implementations, including GNU Make.
If the target makefile exists, then make will remake the makefile before doing anything else, and when it's finished it'll restart processing with the new makefile. That means that your makefile target may be run even if you don't ask for it.
Since the default action when you do make -f makefile.boot is to run make, then that's at least two potential runs of the makefile target's actions right there, before it's even looked at the product target. I can't quite make this add up to five runs, but I'd lay money that it's this special behaviour that's causing the unexpected repeats.

Makefile.am - Manual target prerequisite + addprefix?

I have a autotool project where part of the source code is downloaded dynamically from the net (because of IP rights preventing direct redistribution) and then built.
I have a Makefile.am that works but I'm not happy about some of it's aspects.
Here it is:
INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
AM_CFLAGS = -fPIC -Wall ${SYMBOL_VISIBILITY}
LIBVERSION=0:0:0
REFSRC_PATH=refsrc
REFSRC_SRC=refsrc/dtx.c refsrc/globdefs.c refsrc/host.c refsrc/mathhalf.c refsrc/sp_enc.c refsrc/sp_rom.c refsrc/vad.c refsrc/err_conc.c refsrc/homing.c refsrc/mathdp31.c refsrc/sp_dec.c refsrc/sp_frm.c refsrc/sp_sfrm.c
${REFSRC_PATH}/.downloaded:
./fetch_sources.py "${REFSRC_PATH}"
for f in `ls -1 "${REFSRC_PATH}"/*.{c,h}`; do \
sed -i -e"s/round/round_l2s/" "$$f"; \
done
touch $#
${REFSRC_PATH}/dtx.c: ${REFSRC_PATH}/.downloaded
lib_LTLIBRARIES = libgsmhr.la
libgsmhr_la_SOURCES = libgsmhr.c $(REFSRC_SRC)
clean-local:
-rm -rf ${REFSRC_PATH}
So essentially, libgsmhr.c is my main wrapper, then I download the source code in a refsrc/ subdirectory and patch it a little.
First problem is that in REFSRC_SRC I would have loved to use a $(addprefix ...) instead of repeating refsrc/ in front of each .c file. But that doesn't seem to work and autoreconf complains a little.
Failure details (when removing the refsrc/ prefix from REFSRC_SRC= and using $(addprefix ${REFSRC_PATH}/, ${REFSRC_SRC}) on the dependency list):
bash$ autoreconf -i
libgsmhr/Makefile.am:19: addprefix ${REFSRC_PATH}/, ${REFSRC_SRC}: non-POSIX variable name
libgsmhr/Makefile.am:19: (probably a GNU make extension)
(configure works fine)
bash$ make
...
make[2]: Entering directory `/tmp/ram/gapk.build/libgsmhr'
CC libgsmhr.lo
CCLD libgsmhr.la
make[2]: Leaving directory `/tmp/ram/gapk.build/libgsmhr'
...
(So as you see it didn't include any of the downloaded .c files, didn't even download them at all. The compile works because libgsmhr.c is a stub that doesn't use the symbols in those file yet)
Second problem is this rule:
${REFSRC_PATH}/dtx.c: ${REFSRC_PATH}/.downloaded
I have to explicitely list the first file (dtx.c) instead of using a wildcard like:
${REFSRC_PATH}/%.c: ${REFSRC_PATH}/.downloaded
If I try to use the wildcard, then autoreconf complains and also it just doesn't work ... (pattern doesn't match somehow).
Failure detail:
bash$ autoreconf -i
libgsmhr/Makefile.am:16: `%'-style pattern rules are a GNU make extension
(configure works fine)
bash$ make
...
make[2]: *** No rule to make target `refsrc/dtx.c', needed by `dtx.lo'. Stop.
...
Sylvain
You seem to be writing a makefile in GNUMake style, but actually running some other version of Make. If it's not obvious what autoreconf is calling, you could insert a rule in the makefile:
dummy:
#echo using $(MAKE)
$(MAKE) -v
If this theory proves correct, you can either persuade autoconf to use GNUMake, or write for the version it's using.

Resources