Makefile can't find a target that is already there - c

So I've got the following folder structure
makefile
src/my_lib.c
src/myhead.h
and I'm trying to compile *my_lib.c* with the header myhead.h as a library. This is the makefile. I attempt to put the obj files in OBJFOLDER and the compiled library in the OUTPUTFOLDER
PLUGNAME=my_lib
SOURCEFOLDER=src
OUTPUTFOLDER=bin
OBJFOLDER=bin/obj
OBJS=$(PLUGNAME).o
DEPS=myhead.h
# Configuration finishes here
_OBJS = $(patsubst %,$(OBJFOLDER)/%,$(OBJS))
_DEPS = $(patsubst %,$(SOURCEFOLDER)/%,$(DEPS))
ifeq ($(OS),Windows_NT)
EXT = .dll
else
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Linux)
EXT = .so
endif
endif
all : $(OUTPUTFOLDER)/$(PLUGNAME)$(EXT)
$(OUTPUTFOLDER)/$(PLUGNAME)$(EXT) : $(_OBJS)
gcc -Wl,--add-stdcall-alias -shared -o $# $(_OBJS)
$(OBJFOLDER)/%.o: $(SOURCEFOLDER)/%.c $(_DEPS)
mkdir -p $(OUTPUTFOLDER)
mkdir -p $(OBJFOLDER)
gcc $(foreach d, $(INC), -I$d) -c $< -o $#
.PHONY: clean
clean :
rm -f $(OBJFOLDER)/*.o $(OUTPUTFOLDER)/$(PLUGNAME)$(EXT) $(SOURCEFOLDER)/TSDRPlugin.h
When I do make all it fails
make: *** No rule to make target `bin/obj/my_lib.o', needed by `bin/
my_lib.dll'. Stop.
I have no idea how this could be possible since I already have defined
$(OBJFOLDER)/%.o: $(SOURCEFOLDER)/%.c $(_DEPS)
Strangely if I change the above line in the makefile, to
bin/obj/my_lib.o: $(SOURCEFOLDER)/%.c $(_DEPS)
I now get
make: *** No rule to make target `src/%.c', needed by `bin/obj/my_lib.o'. Stop.

Your second error is because by removing the % in the target you've turned this into an explicit rule, not a pattern rule. So, the % in the prerequisite is not replaced.
Your first error means that for some reason make is deciding that your pattern rule doesn't match. This means, usually, that make can't find and doesn't know how to create one of the prerequisites. I recommend you run make with the -d flag and see why make decides your rule doesn't apply.
What version of GNU make are you using? Some very old versions would not match pattern rules if the directory that the target was to be placed into didn't exist already.

The problem was that header was missing... Stupid mistake on my side.
I overlooked it, because this was a snippet from a longer makefile that was supposed to copy over the header but it didn't which means that this line was outputting the error. Stupid me...

Related

Simplest C makefile using implicit rules

I know it is not optimal at all to rely on make's implicit rules but
my goal is to understand why they are not working in this case.
I want to write the simplest makefile one can write for a C project
without having to specify the sources.
I have tried to run make -d but the ouput is too big and verbose to
really be helpful.
I have written makefiles for some time and I believe I am familiar with how it
works. I am pretty sure I have managed to get implicit rules to work for me both
compiling and linking in the past but apparently I am forgetting something.
Here's what I have tried :
SRCS = $(wildcard *.c)
OBJS = ${SRCS:.c=.o}
NAME=exe
${NAME}: ${OBJS}
clean:
rm -rf *.o
fclean: clean
rm -rf ${NAME}
re: fclean ${NAME}
.PHONY: clean fclean re
It almost works but it doesn't link.
I am using gnu make version 4.3
Your Makefile doesn't execute the link step because there is only a very simple implicit rule for linking. From the documentation:
Linking a single object file
n is made automatically from n.o by running the C compiler to link the program. The precise recipe used is $(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS).
This rule does the right thing for a simple program with only one source file. It will also do the right thing if there are multiple object files (presumably coming from various other source files), one of which has a name matching that of the executable file. Thus,
x: y.o z.o
In other words, for your Makefile to work, NAME needs to match the basename of one of your object files.
For example, if I have your Makefile and a single source file named hello.c, I can run:
make NAME=hello
And see the result:
cc -c -o hello.o hello.c
cc hello.o -o hello

Issues with makefile producing fatal error "Don't know how to make target" using C source files

I am having an issue with this makefile giving the fatal error: "Don't know how to make target calc.o". The naming is correct along with being in the working directory, and the other issue is that when I switch the order of the object files for default target file it will say it does not know how to make that target either, so the order does not seem to change anything or be one specific file. I am running the make command on a sun sparc unix server as well. The makefile is pasted below:
#The following rule tells make about possible suffixes
#(extensions) of file names.
.SUFFIXES: .c .o
#The following definition of CC ensures that
#gcc will be used to compile the C source files.
CC = gcc
#The following definition of CFLAGS ensures that
#the debugger can be used with the executable file (p1)
#created by running make.
CFLAGS = -g
#The following rule tells make how a ".o" file should
#be created from the corresponding ".c" file.
#Note that the "-c" option must be used here since we are
#compiling source files separately. (Note that the line
#following the ".c.o:" line begins with the "tab" character.)
.c.o:
$(CC) $(CFLAGS) -c $<
#Dependency rule for the default target and how the
#default target is to be created. (Note that the line
#following the dependency rule begins with the "tab"
#character.)
p2: main.o textToBin.o binToText.o calc.o
gcc main.o textToBin.o binToText.o calc.o -o p2
#Dependency rules for other targets. (We don't need to
#specify how these targets are created since we have already
#given a general rule for creating a ".o" file from the
#corresponding ".c" file.)
#NO HEADER FILES
#Target for removing unnecessary files.
clean:
rm -f *.o core

makefile prerequisite appears older then target even if it was built afterwards

I am trying to add more then one file created in different directories to a static library but apparently it does not work as expected.
My makefile structure is something like this:
./src/drv/platform/AVR/
- hal
- hw
--- spi
--- uart
In hal I define a library name in $(LIB_TARGET) named libHal and all the *.o files should be archived in that library.
In hw I define another library name in $(LIB_TARGET) named libHw and all *.o files in hw/spi and hw/uart should go in that library: first the library libHw is created with the object files in hw/spi and they are never missed, then the objects in hw/uart are created and should be added to libHw.
In each subdirectory a generic makefile with suffix rules is ran that creates the object files and then should add each *.o to the library. At the end of the run I should have in another library directory(as in another location) 2 libs, libHal and libHw, libHal contains everything in hal, libHw everything in hw.
In this case the directory hw does not have any source files and looks like this:
SUBDIRS:= spi uart
LIB_TARGET = libHw.a
.PHONY: $(SUBDIRS) clean all
default: all
$(SUBDIRS)::
$(MAKE) -C $# $(MAKECMDGOALS)
all clean : $(SUBDIRS)
Each of the uart and spi subdirs hold something like this:
include $(TGT_BASE)/make/generic.mk
SRCS := uart.c
include $(TGT_BASE)/make/rules.mk
The file generic.mk only holds generic platform definitions.
The code for the generic makefile rules.mk with all the suffix rules.
.PHONY : all clean
OBJS = $(SRCS:.c=.o)
DEPS = $(OBJS:.o=.d)
LIB_TARGETT = $(LIB_DIR)/$(LIB_TARGET)
### Archive into a library file (.a)
$(LIB_DIR)/%.a: $(OBJS)
#echo $(MSG_L)
#echo 'Adding $^ to library $#'
$(AR) $(ARFLAGS) $# $^
#echo $(MSG_L)
### rule for c files
%.o: %.c
#echo $(MSG_C)
$(CC) -c $(CFLAGS) $(MODULES_INC) $(TGT_LOCAL_INCLUDES) $< -o $#
#echo $(MSG_C)
### make dependencies
%.d: %.c
#echo $(MSG_D)
$(CC) -E -MM $(CFLAGS) $(MODULES_INC) $(TGT_LOCAL_INCLUDES) $(CURDIR)/$< > $#
#echo $(MSG_D)
all: $(DEPS) $(OBJS) $(LIB_TARGETT)
clean:
$(RM) -rf *.o *.d .depend
The makefile that exists in most
Now the problem is that sometimes some of the *.o files in hw/uart are not added to the library defined in hw. Running make in debug reveals that make itself considers the prerequisites for the library to be older then the last access to the library so they are missed.
Found an implicit rule for 'F:/automata/tmp/remake//tmp/app/brick/lib/atmega328p/libHw.a'.
Pruning file 'uart.o'.
Finished prerequisites of target file 'F:/automata/tmp/remake//tmp/app/brick/lib/atmega328p/libHw.a'.
Prerequisite 'uart.o' is older than target 'F:/automata/tmp/remake//tmp/app/brick/lib/atmega328p/libHw.a'.
To explain better how this goes when it works here is an example
make[7]: Entering directory 'F:/automata/tmp/remake/src/drv/platform/AVR/hw/uart
'
-------- make c --------
avr-gcc -c -Wall -Werror -Os -mmcu=atmega328p -IF:/automata/tmp/remake//tmp/ap
p/brick -IF:/automata/tmp/remake/src/common/h -IF:/automata/tmp/remake/src/drv/p
latform/AVR/hw/spi -IF:/automata/tmp/remake/src/drv/platform/AVR/hw/uart -IF:/au
tomata/tmp/remake/src/modules/interface/cli -IF:/automata/tmp/remake/src/drv/pl
atform/AVR/hw/uart uart.c -o uart.o
-------- make c --------
------- make Lib -------
Adding uart.o to library F:/automata/tmp/remake//tmp/app/brick/lib/atmega328p/li
bHw.a
avr-ar rcs F:/automata/tmp/remake//tmp/app/brick/lib/atmega328p/libHw.a uart.o
------- make Lib -------
make[7]: Leaving directory 'F:/automata/tmp/remake/src/drv/platform/AVR/hw/uart'
And here is an example if it when it is not working
make[7]: Entering directory 'F:/automata/tmp/remake/src/drv/platform/AVR/hw/uart
'
-------- make c --------
avr-gcc -c -Wall -Werror -Os -mmcu=atmega328p -IF:/automata/tmp/remake//tmp/ap
p/brick -IF:/automata/tmp/remake/src/common/h -IF:/automata/tmp/remake/src/drv/p
latform/AVR/hw/spi -IF:/automata/tmp/remake/src/drv/platform/AVR/hw/uart -IF:/au
tomata/tmp/remake/src/modules/interface/cli -IF:/automata/tmp/remake/src/drv/pl
atform/AVR/hw/uart uart.c -o uart.o
-------- make c --------
make[7]: Leaving directory 'F:/automata/tmp/remake/src/drv/platform/AVR/hw/uart'
I am using make 3.82.90 and Windows 7.
So any idea how I can force make to not miss those objects? Or to see their real time of creation and properly add them to the library? Remember, sometimes they are added, but sometimes they are not.
Thank you.
When you say it always works when you run it with make all --debug=a it always works: which part of that matters? If you run make all does it always work? Or if you run make --debug=a does it always work? Or do you have to use both to make it always work?
Since you're not showing all the makefile, we can't say much. For example, how are you setting the value of OBJS? Where and how do you define the rules that build object files (or are you using make's built-in rules for that)? That information is critical. It looks like what's happening is that make is asking you to build one file but your rules build a different file, so make sees that the file it expects was not actually updated and doesn't do anything.
Also, it's very confusing that in your overview you talk about things like dir1, dir2, dir2.1, etc. but then in the error output you provide completely different paths. We can't determine how the "real" pathnames in your example match up with the pseudo-paths in your overview.
Please either use real paths everywhere, or edit your example output to use the pseudo-paths, so we can see which paths are doing what.

No rule to make something.o even though %.o is defined

I'm new to the forum, so I hope I'm doing things right.
I'm writing from scratch a Makefile for a C project. It was working at some point, then I tried to improve it a little (including separate folders), and I got the well-known error "No rule to make target "obj/autresFonctions.o", needed for "CUR"". Or similar, since it's not in english and I translated.
That seems quite weird since the rule I'm expecting to work is using %.o and should match anyhting. Thus I don't think it could be a typo.
Here is the Makefile :
EXE=prgm
CC=gcc
SRC_DIR=src
OBJ_DIR=obj
INCLUDE_DIR=include
_FICHIERS_H = autresFonctions.h calculPrealable.h constantes.h fonctionsAnnexes.h fonctionBoucles.h lectureFichiers.h main.h
FICHIERS_H = $(patsubst %, $(INCLUDE_DIR)/%, $(_FICHIERS_H))
_OBJ = autresFonctions.o calculPrealable.o fonctionsAnnexes.o fonctionsBoucles.o lectureFichiers.o main.o
OBJ = $(patsubst %, $(OBJ_DIR)/%, $(_OBJ))
FLAGS=-Wall -Wextra
CUR: $(OBJ)
$(CC) -o $(EXE) $^
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(FICHIERS_H)
$(CC) $(FLAGS) -c -o $# $<
clean:
rm $(OBJ) $(EXE)
I'm assuming it's the same for the others .o, because I also tried switching the first two .o in _OBJ , and I got the same error with calculPrealable.o
I'm just typing "make" when compiling, in order to get CUR, the main target. I'm located in the main directory, which contains include/ (with the .h), src/ (with the .c) and obj/ (empty).
EDIT : I forgot to say, but I'm using the usual GNU make.
The pattern rule only matches if ALL of the rule matches. It's not enough to just match the target: make must also be able to find (or make) the prerequisite pattern(s) and all other prerequisites listed in the rule.
If one thing doesn't match, then the rule doesn't match.
You can use make -d to see what files make is trying to build, and see which one doesn't exist and causes the rule to fail.
PS. This is all assuming you're using GNU make, which you don't say specifically.

Why does this makefile not apply includes to all objects?

This makefile does not behave as I expect. I want it to build .o files for each .c file in the current directory and subdirectories, and put them in a static library. However, it stops applying my $(INCS) after the first or second file. When it tries to build the second .o file, I don't see the -I paths in the build line and it complains about not finding a header file therein. Names have been genericized to simplify things. I'm using cygwin on Windows XP. I'm using an ARM cross compiler that is not under the cygwin tree. I based this makefile off an answer here. There are only about two dozen .c files so the overhead of creating the dependency files this way isn't a big deal.
# Project specific options
CC = my-cross-gcc
INCS := -I. -Iinc
INCS += -Imy/inc/path
CFLAGS := -Wall -fPIC -static -cross-compiler-specific-options
OUT := bin/libmylib.a
MKDIR:=mkdir -p
### Generic C makefile items below:
# Add .d to Make's recognized suffixes.
SUFFIXES += .d
NODEPS:=clean
#Find all the C files in this directory, recursively
SOURCES:=$(shell find . -name "*.c")
#These are the dependency files
DEPFILES:=$(patsubst %.c,%.d,$(SOURCES))
OBJS:= $(patsubst %.c,%.o,$(SOURCES))
#Don't create dependencies when we're cleaning, for instance
ifeq (0, $(words $(findstring $(MAKECMDGOALS), $(NODEPS))))
-include $(DEPFILES)
endif
#This is the rule for creating the dependency files
%.d: %.c
$(CC) $(INCS) $(CFLAGS) -MM -MT '$(patsubst %.c, %.o,$(patsubst %.c,%.o,$<))' $< > $#
#This rule does the compilation
%.o: %.c %.d %.h
$(CC) $(INCS) $(CFLAGS) -o $# -c $<
# Now create a static library
all: $(OBJS)
#$(MKDIR) bin
ar rcsvq $(OUT) $(OBJS)
clean:
rm -rf $(OBJS) $(OUT) $(DEPFILES)
Why does this makefile not apply $(INCS) when building subsequent .o files? How do I fix it? Output resembles this:
$ make all
my-cross-gcc -I. -Iinc -Imy/inc/path -<compiler options> -o firstfile.o -c firstfile.c
my-cross-gcc -I. -Iinc -Imy/inc/path -<compiler options> -o secondfile.o -c secondfile.c
my-cross-gcc -<compiler flags> -o thirdfile.o -c thirdfile.c
thirdfile.c:23:18: fatal error: myinc.h: No such file or directory
compilation terminated.
When I go to the command line and type in the gcc line to build thirdfile.o and use the -I paths, the object file is successfully built.
There are two different mechanisms for handling header files at work here:
When the compiler is trying to build foo.o from foo.c, and in foo.c it encounters #include "foo.h", it goes looking for foo.h. The -I flags tell it where to look. If it is invoked without the flags it needs to find foo.h, it will complain and die.
When Make is trying to build foo.o, and considering which rule to use, it looks at the prerequisites. The prerequisites for your rule are foo.c foo.d foo.h, so it goes looking for those prerequisites. How is it to know where foo.h is? Note that the compiler flag inside one of its commands is of no use-- it won't make any deductions about that. If it can't find (and doesn't know how to make) a prerequisite, it will reject that rule and look for another one, such as the implicit %.o rule which knows nothing about your $(INCS) variable, and that leads you to the problem described above.
If this is the problem (and you can check by looking at the locations of the headers and doing some experiments) you have a couple of options:
A) You can use the implicit rule, and it's variables. Just add INCS to CFLAGS and you'll probably get the results you want. This tells the compiler what to do, but it still leaves Make in the dark about the dependencies, so you'll probably have to double-check that your dependency handling is correct.
B) You can tell Make where to find the header files:
vpath %.h inc my/inc/path
(You may notice that this is redundant with your INCS variable, and redundancy is bad-- you can eliminate this redundancy, but I urge you to get it working first.)
I'm going to guess that you have files named firstfile.h, secondfile.h, but no file named thirdfile.h?
I would then suppose that make cannot use the rule you gave it because and can't find or build the .h file. So it decides to use the default implicit rule instead.
All I can imagine is that for "thirdfile" your depfile is somehow out-of-date or corrupt. Perhaps it is bad enough that it's confusing make into calling some other default target.

Resources