make: pattern rule not applied? - c

Follow-up: Set up a development environment on Linux targeting Linux and Windows
The project dir looks like this:
/pps
/src
/obj
/bin
Makefile
And the content of Makefile is this:
OBJ_DIR = obj
SRC_DIR = src
BIN_DIR = bin
INCLUDE = -I./$(SRC_DIR)
LIBS =
_SRCS = print_current_dir.c test_main.c
_OBJS = print_current_dir.o test_main.o
SRCS = $(addprefix $(SRC_DIR)/,$(_SRCS))
OBJS = $(addprefix $(OBJ_DIR)/,$(_OBJS))
$(OBJ_DIR)/%.o: %.c %.h
$(CC) -c -o $(OBJ_DIR)/$# $< $(CFLAGS)
all: $(BIN_DIR)/pps-linux $(BIN_DIR)/pps-win32
$(BIN_DIR)/pps-linux: $(OBJS)
CC = cc
CFLAGS = -g -Wall $(INCLUDE) $(LIBS)
$(BIN_DIR)/pps-win32: $(OBJS)
CC = i586-mingw32msvc-cc
CFLAGS = -g -Wall $(INCLUDE) $(LIBS)
.PHONY: clean
clean:
rm -f $(OBJS) $(SRC_DIR)/~ core $(BIN_DIR)/*
The files print_current_dir.c and test_main.c are just for testing.
This makefile doesn't work:
$ make
make: *** No rule to make target `obj/print_current_dir.o', needed by `bin/pps-linux'. Stop.
I think the problem is with the %.o rule. I'm sure it is trivial, but I'm not very experienced with make.
Thank you.

This rule:
$(OBJ_DIR)/%.o: %.c %.h
specifies that obj/foo.o depends on foo.c, not src/foo.c. There is no foo.c, so this rule cannot be applied (hence the error message).
This should do the job:
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(SRC_DIR)/%.h

Related

Makefile doesn't match obj file

I have to work in a C project and i have problem with the make. The file structure is:
dir
--/bin
--/src
all the sources files (.c)
--/includes
all the includes (.h)
makefile
makefile is:
CC = gcc
RES =
_OBJ = paciente.o utils.o obrasocial.o pacienteobrasocial.o orm.o
profespecialidad.o profesional.o especialidad.o turnos.o $(RES)
LINKOBJ = main.o utils.o $(RES)
MAINOBJ = main.o
MAINSRC= main.c
LIBS = -L"/usr/lib"
IDIR =/includes
INCS = -I$(IDIR)
BIN = tpfinalc
_DEPS = config.h utils.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
ODIR=/bin
CFLAGS = $(INCS) $(LIBS) -lpq
RM = rm -f
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
SDIR = /src
_SRC = especialidad.c obrasocial.c orm.c paciente.c
pacienteobrasocial.c profesional.c profespecialidad.c turnos.c utils.c
SRC = $(patsubst %,$(SDIR)/%,$(_SRC))
VPATH = src
.PHONY: all all-before all-after clean clean-custom
all: all-before tpfinalc all-after clean
$(BIN): $(OBJ)
$(CC) $(LINKOBJ) -o tpfinalc $(CFLAGS)
$(ODIR)/$(MAINOBJ): MAINSRC $(DEPS)
$(CC) -c MAINSRC -o $(ODIR)/$(MAINOBJ) $(CFLAGS)
$(ODIR)/%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
I guess that this should'be correct, but when I make my c files the console indicates that there isn't any rule to build bin/paciente.
Anyone have an idea why? Thanks You.
One error is that /includes is an absolute path which does not exist (same applies to all other paths here). What you need is a relative path: includes or, if you like typing, ./includes.
Another error is that you omit paths in the dependencies and rules, so that make never finds your files. E.g.:
$(ODIR)/%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
Should really be:
bin/%.o: src/%.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
All paths should be relative to the current directory, which is where your makefile is.

Makefile relink error

I am trying to get this makefile relink and not recompile unessecarily files that aren't modified. The "libft" is my library and doesnt have any errors. The error that I am having when doing
make
is :
make: *** No rule to make target `main.o', needed by `ft_printf'. Stop.
My makefile is:
NAME = ft_printf
SRC = main.c\
ft_printf.c\
parser_main.c\
utils.c\
debug_funcs.c
OBJ = $(SRC:.c=.o)
SRC_PATH = srcs/
SRC_POS = $(addprefix $(SRC_PATH),$(SRC))
INC = -I includes
LIBFT = libft/libft.a
CC = gcc
FLAGS = -Wall -Wextra -Werror
all: $(NAME)
$(NAME): $(OBJ)
$(CC) $(FLAGS) $(OBJ) -o $(NAME) $(LIBFT)
%.o: %.c
$(CC) -o $# -c $< $(FLAGS)
$(LIBFT):
make -C ./libft/
clean:
rm -f $(OBJ)
make clean -C ./libft/
fclean: clean
rm -f $(NAME)
make fclean -C ./libft/
re: fclean all
Any idea ? I can't figure it out and i think it's because %.o:%.c isn't called
Given the existence of these variables:
SRC_PATH = srcs/
SRC_POS = $(addprefix $(SRC_PATH),$(SRC))
I'm guessing that your source files actually live in srcs/ whereas you're building your object files in . So this pattern rule:
%.o: %.c
when trying to match main.o won't find a main.c since that file really is srcs/main.c. Since that pattern doesn't match, the rule itself isn't considered, and since no other rule is found, you get an error.
Instead, try:
%.o : $(SRC_PATH)/%.c
$(CC) -o $# -c $< $(FLAGS)

My Makefile always builds all files

This is running on FreeBSD which uses PMake instead of GMake.
This is my first Makefile. I used Google a lot to help create this as well as sources such as 'PMake — A Tutorial'. The only problem I can't solve is that every time I run the Makefile, it will compile every file even when there are no changes.
I have four directories. src for my source files, include for my headers, obj for the output and bin for the executable.
What I'm doing is scanning the source folder and creating a list of files to use for both the source and object as well as the headers. Typically I run 'make debug' for debugging and 'make myservice' otherwise.
If I run 'make clean', 'make debug', and 'make debug' it will clean my folders, make all files and then proceed to remake all files instead of doing nothing.
Based on my searching, I'm leaning towards the $(OBJ) rule being the problem, but I don't quite get that. In order for my target and debug rules to build they need to know how to build the objects.
CC = clang
BINDIR = $(.CURDIR)/bin
OBJDIR = $(.CURDIR)/obj
SRCDIR = $(.CURDIR)/src
INCDIR = $(.CURDIR)/include
CFLAGS = -Wall -I/usr/local/include -I$(INCDIR)
LFLAGS = -lm -lpq -lpthread
LIBDIR = -L/usr/local/lib
_SRC != ls $(SRCDIR)/*.c
SRC = ${_SRC:T}
INC != ls $(INCDIR)/*.h
OBJ = ${SRC:S/src/obj/g:.c=.o}
TARGET = myservice
$(TARGET): $(OBJ)
$(CC) -o $(BINDIR)/$# $(OBJ) $(CFLAGS) $(LIBDIR) $(LFLAGS)
debug: $(OBJ)
$(CC) -g -O0 -o $(BINDIR)/$(TARGET) $(OBJ) $(CFLAGS) $(LIBDIR) $(LFLAGS)
$(OBJ) : $(SRCDIR)/$(.PREFIX).c $(INCDIR)/$(.PREFIX).h
$(CC) -c $< $(CFLAGS)
.PHONY: clean
clean:
rm -rf $(OBJDIR)/*.o $(BINDIR)/$(TARGET)
edit - New Makefile
New Makefile. Doesn't rebuild if no changes. Has no debug, still issues figuring out debug.
CC = clang
BINDIR = $(.CURDIR)/bin
OBJDIR = $(.CURDIR)/obj
SRCDIR = $(.CURDIR)/src
INCDIR = $(.CURDIR)/include
CFLAGS = -Wall -I/usr/local/include -I$(INCDIR)
LFLAGS = -lm -lpq -lpthread
LIBDIR = -L/usr/local/lib
TARGET = $(BINDIR)/myservice
_SRC != ls $(SRCDIR)/*.c
SRC = ${_SRC:T}
INC != ls $(INCDIR)/*.h
OBJ = ${SRC:S/src/obj/g:.c=.o}
$(TARGET): $(OBJ)
$(CC) -o $(TARGET) $(OBJ) $(CFLAGS) $(LIBDIR) $(LFLAGS)
$(OBJ) : $(SRCDIR)/$(.PREFIX).c $(INCDIR)/$(.PREFIX).h
$(CC) $(CFLAGS) -c $< -o $#
.PHONY: clean
clean:
rm -rf $(OBJDIR)/*.o $(TARGET)
edit - Working Makefile
Added if conditional for debugging purposes.
CC = clang
BINDIR = $(.CURDIR)/bin
OBJDIR = $(.CURDIR)/obj
SRCDIR = $(.CURDIR)/src
INCDIR = $(.CURDIR)/include
CFLAGS = -Wall -I/usr/local/include -I$(INCDIR)
.if make(debug)
CFLAGS += -g -O0
.endif
LFLAGS = -lm -lpq -lpthread
LIBDIR = -L/usr/local/lib
TARGET = $(BINDIR)/myservice
_SRC != ls $(SRCDIR)/*.c
SRC = ${_SRC:T}
INC != ls $(INCDIR)/*.h
OBJ = ${SRC:S/src/obj/g:.c=.o}
all: $(TARGET)
debug: $(TARGET)
$(TARGET): $(OBJ)
$(CC) -o $(TARGET) $(OBJ) $(CFLAGS) $(LIBDIR) $(LFLAGS)
$(OBJ): $(SRCDIR)/$(.PREFIX).c $(INCDIR)/$(.PREFIX).h
$(CC) $(CFLAGS) -c $< -o $#
.PHONY: clean
clean:
rm -rf $(OBJDIR)/*.o $(TARGET)
The second make debug cannot do nothing, debug is phony target, not an actual output file, at least the link phase will be re-run.
Furthermore, re-running the link phase with -g -O0 would not recompile you source files with debug information and no optimizations.
Incidentally, the $(TARGET) rule is a phony rule too, it produces $(BINDIR)/$(TARGET), not $(TARGET).
You should rewrite your makefile with different rules to make object and binary output files in different directories for debug and release modes. gmake patterns make this easy to write, I don't know about pmake or cmake for this purpose.

make: *** No rule to make target

Thanks for the responses. I found that this worked — I don't know why though.
all: $(OUT)
$(OBJ_DIR)/%.o: %.c
$(CC) $(CCFLAGS) -o $# -c $< $(INCLUDES)
$(OUT): $(OBJ)
ar rcs $(OUT) $(OBJ)
cp DIMEFILEAPPSAUTH.h ../include
.PHONY: clean
Below is a makefile I have. I keep getting the error make: *** No rule to make target but cannot see what is wrong in this case. The ".c" files exist in the current directory. I'm not sure why makefile cannot see them — can you explain?
DimeFileAppsAuth/src> ls
db_get_DIMEFILEAPPSAUTH.c db_reset_query_DIMEFILEAPPSAUTH.c Makefile
db_add_DIMEFILEAPPSAUTH.c db_print_DIMEFILEAPPSAUTH.c db_update_DIMEFILEAPPSAUTH.c
db_delete_DIMEFILEAPPSAUTH.c db_reset_DIMEFILEAPPSAUTH.c
Running the make
DimeFileAppsAuth/src> make
make: *** No rule to make target `../obj/db_add_DIMEFILEAPPSAUTH.o', needed by `../lib/lib_dime_file_apps.a'. Stop.
The Makefile
# clear out all suffixes
.SUFFIXES:
# list only those we use
.SUFFIXES: .o .c
# define a suffix rule for .c -> .o
.c.o :
$(CC) $(CFLAGS) -c $<
FILE_DIVERSION=$(IMG_PROJ_HOME)/dime/basics/BasicsLink
INC_DIR =../include
LIB_DIR =../lib
OBJ_DIR =../obj
BIN_DIR =../bin
CUR_DIR = .
OUT = $(LIB_DIR)/lib_dime_file_apps.a
BIN_OUT = $(BIN_DIR)/test_run
# include directories
INCLUDES = -I$(INC_DIR) -I$(FILE_DIVERSION)/include -I$(ORACLE_HOME)/rdbms/public -I/usr/local/include
# library paths
LIBS = -L$(LIB_DIR) -ldime_direct -L$(FILE_DIVERSION)/lib -loutput_files -lquerylib -lsql_common -lsql_common -L$(ORACLE_HOME)/lib -lclntsh -L$(ORACLE_HOME)/lib `cat $(ORACLE_HOME)/lib/sysliblist` -L/usr/local/lib -lm
CC=gcc
CCFLAGS=-w -O2 -unused-variable -Wall -fPIC -c -g -rdynamic
_DEPS = DIMEFILEAPPSAUTH.h
DEPS = $(patsubst %,$(INC_DIR)/%,$(_DEPS))
_OBJ = db_add_DIMEFILEAPPSAUTH.o db_delete_DIMEFILEAPPSAUTH.o db_get_DIMEFILEAPPSAUTH.o db_get_SEQ_DIMEFILEAPPSAUTH.o db_print_DIMEFILEAPPSAUTH.o db_reset_DIMEFILEAPPSAUTH.o db_reset_query_DIMEFILEAPPSAUTH.o db_special_DIMEFILEAPPSAUTH.o db_update_DIMEFILEAPPSAUTH.o
OBJ = $(patsubst %,$(OBJ_DIR)/%,$(_OBJ))
_BIN = db_add_DIMEFILEAPPSAUTH.o db_delete_DIMEFILEAPPSAUTH.o db_get_DIMEFILEAPPSAUTH.o db_get_SEQ_DIMEFILEAPPSAUTH.o db_print_DIMEFILEAPPSAUTH.o db_reset_DIMEFILEAPPSAUTH.o db_reset_query_DIMEFILEAPPSAUTH.o db_special_DIMEFILEAPPSAUTH.o db_update_DIMEFILEAPPSAUTH.o test_this.o
BIN = $(patsubst %,$(BIN_DIR)/%,$(_BIN))
all: $(OUT)
$(OBJ_DIR)/%.o: %.c $(DEPS)
$(CC) $(CCFLAGS) -o $# $< $(INCLUDES)
$(OUT): $(OBJ)
ar rcs $(OUT) $(OBJ)
cp DIMEFILEAPPSAUTH.h ../include
exec: $(BIN) $(OUT)
$(CC) -o $(BIN_OUT) $(BIN) $(LIBS)
rm $(BIN_DIR)/*.o
.PHONY: clean
The make error occurs when it comes to this line "$(OUT): $(OBJ)". Please check whether the file named "db_add_DIMEFILEAPPSAUTH.o" exists in the directory "../obj"

Makefile C subdirectory rule to make obj

I am running a simple Makefile with no problems:
CC=gcc
CFLAGS= -std=c99 -ggdb -Wall -I.
DEPS = hellomake.h
OBJ = hellomake.o hellofunc.o
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
hellomake: $(OBJ)
gcc -o $# $^ $(CFLAGS)
The files are in the main project's directory:
./project/Makefile
./project/hellomake.c
./project/hellomake.h
Then I tried to organized the files, and put things like:
./project/Makefile
./project/src/hellomake.c
./project/include/hellomake.h
and extra subdirectories directories:
./project/lib
./project/obj
Then the new version of the Makefile:
IDIR =include
CC=gcc
CFLAGS= -std=c99 -ggdb -Wall -I$(IDIR)
ODIR=obj
LDIR =lib
LIBS=-lm
_DEPS = hellomake.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
_OBJ = hellomake.o hellofunc.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
$(ODIR)/%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
hellomake: $(OBJ)
gcc -o $# $^ $(CFLAGS) $(LIBS)
.PHONY: clean
clean:
rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~
I am compiling on Linux using Emacs with the gcc compiler:
$ gcc --version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Then, I run on Emacs:
<Esc>
x
compile
make
And it gives the message:
"./project/src/" -*-
make: *** No rule to make target `obj/hellomake.o', needed by `hellomake'. Stop.
Compilation exited abnormally with code 2 at Wed Oct 3 17:10:01
What rule should be missing to be included in the Makefile file?
All comments and suggestions are highly appreciated.
Thanks for your suggestion, it is added to the code. Then the compiler complains:
make -k
make: *** No rule to make target `src/hellomake.c', needed by `obj/hellomake.o'.
make: *** No rule to make target `../include/hellomake.h', needed by `obj/hellomake.o'.
make: Target `obj/hellomake.o' not remade because of errors
Some other suggestion?
Thanks in advance!
To fix the error make: *** No rule to make target 'obj/hellomake.o', needed by 'hellomake'. Stop.
Change this line:
$(ODIR)/%.o: %.c $(DEPS)
To:
$(OBJ): $(ODIR)/%.o: src/%.c $(DEPS)
This creates a rule for all objects in the $(OBJ) variable. The second parameter ('$(ODIR)/%.o') extracts the file name from the full path in order to pass just the file name to the third parameter ('src/%.c').
Ok. Now I am trying another example found here [ How can I create a Makefile for C projects with SRC, OBJ, and BIN subdirectories? ] and here it goes:
TARGET = hi.sh
CC = gcc
# compiling flags here
CFLAGS = -std=c99 -ggdb -Wall -I./src
TARGET = bin/hi.sh
LINKER = gcc -o
# linking flags here
LFLAGS = -Wall -I. -lm
# change these to set the proper directories where each files shoould be
SRCDIR = src
OBJDIR = obj
BINDIR = bin
SOURCES := $(wildcard $(SRCDIR)/*.c)
INCLUDES := $(wildcard $(SRCDIR)/*.h)
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
rm = rm -f
$(BINDIR)/$(TARGET): $(OBJECTS)
#$(LINKER) $(TARGETPATH)/$(TARGET) $(LFLAGS) $(OBJECTS)
#echo "Linking complete!"
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
$(CC) $(CFLAGS) -c $< -o $#
#echo "Compiled "$<" successfully!"
.PHONEY: clean
clean:
#$(rm) $(OBJECTS)
#echo "Cleanup complete!"
.PHONEY: remove
remove: clean
#$(rm) $(BINDIR)/$(TARGET)
#echo "Executable removed!"
The files are organized as:
./project/bin/ executable
./project/ojb/*.0
./project/src/*.c and *.h
./project/Makefile
The compiler persists giving only one complaint:
make -k
/usr/bin/ld: cannot open output file /bin/hi.sh: Permission denied
collect2: ld returned 1 exit status
make: *** [bin/bin/hi.sh] Error 1
Thanks a lot for all comments and suggestions!
I think you should change this line
$(ODIR)/%.o: %.c $(DEPS)
change to
$(ODIR)/%.o : %.c $(DEPS)
add a Space after %.o.

Resources