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)
Related
I have a beginner's question about a Makefile. I have a very simple makefile containing:
SHELL = /bin/sh
CC = gcc
CFLAGS = -lm -std=c99 -g -o0
EXEC = test
BUILDDIR = build
OBJDIR = obj
SOURCES = $(shell cat sources.list)
DEPS = $(shell cat headers.list)
OBJ = $(SOURCES:.c=.o)
OBJECTS = $(patsubst %,$(OBJDIR)/%,$(OBJ))
all: $(OBJECTS)
$(CC) $(CFLAGS) $(OBJECTS) -o $(BUILDDIR)/$(EXEC)
$(OBJDIR)/%.o: %.c $(DEPS)
$(CC) -c $< -o $#
clean:
rm -f $(BUILDDIR)/$(EXEC) $(OBJDIR)/*.o
My Problem is, if I try to use this Makefile to compile, it returns the error message:
there is no rule for the target obj/Name.o
What am I doing wrong?
After the first few comments and further research I got to this working Version, but it does not create the object files in the obj folder, so it is not what I aim for
SHELL = /bin/sh
CC = gcc
CFLAGS = -lm -std=c99 -g -o0
EXEC = test
BUILDDIR = build
OBJDIR = obj
SOURCES = $(shell cat sources.list)
DEPS = $(shell cat headers.list)
OBJ = $(SOURCES:.c=.o)
OBJECTS = $(patsubst %,$(OBJDIR)/%,$(OBJ))
all: $(BUILDDIR)/$(EXEC)
$(BUILDDIR)/$(EXEC): $(OBJ)
$(CC) $(CFLAGS) $(OBJ) -o $(BUILDDIR)/$(EXEC)
%.o: %.c $(DEPS)
$(CC) -c $< -o $#
clean:
rm -f $(BUILDDIR)/$(EXEC) $(OBJDIR)/*.o
Are all the files in headers.list present at the right place ?
By the way, this is not a good way to handle dependencies on headers. You should take a look at -MP and -MDD and other options of your preprocessor to generate dependencies.
A classical makefile which should do what you need:
SHELL=/bin/bash
CC=gcc
CFLAGS=-std=c99 -g -o0
LDFLAGS=-lm
EXEC=test
BUILDDIR=build/
OBJDIR=obj/
SOURCES=$(shell cat sources.list)
OBJECTS=$(patsubst %.c,$(OBJDIR)%.o,$(notdir $(SOURCES)))
vpath %.c $(sort $(dir $(SOURCES)))
.PHONY:all mrproper clean depends
all:$(BUILDDIR)$(EXEC)
$(BUILDDIR)$(EXEC):$(OBJECTS)|$(BUILDDIR)
$(CC) $(CFLAGS) $^ -o $# $(LDFLAGS)
$(OBJDIR)%.o:%.c|$(OBJDIR)
$(CC) -c $< -o $#
$(BUILDDIR) $(OBJDIR):
mkdir $#
mrproper:clean
rm -f $(BUILDDIR)$(EXEC)
clean:
rm -f $(OBJECTS)
depends:
#rm -f dependencies.mk
#for i in $(SOURCES); do $(CC) -MM $$i -MT $(OBJDIR)`basename $$i | sed s:.c$$:.o:` >> dependencies.mk; done
include $(wildcard dependencies.mk)
If something is not clear, let me know.
Usage:
make depends
make
Ladies, gentlemen, hello.
I'm trying to create a Makefile in C which will create two libraries
One static,one shared.So far my Makefile works for the static part.
Projet file structure:
//root
//root/src
An other point to mention, this Makefile also creates *.o in my root project directory and the /src dir.
What to do so it only creates object files inside the /src directory ?
Makefile:
SNAME = libmy_printf_`uname -m`-`uname -s`.a
DNAME = libmy_printf_`uname -m`-`uname -s`.so
SRC = $(wildcard src/*.c)
OBJ = $(SRC:.c=.o)
CC = gcc
RM = rm -f
CFLAGS = -W -Wall -ansi -pedantic -Werror -g3 -fPIC
LDFLAGS = -L. -l$(NAME)
STATIC: $(OBJ)
$(CC) -c $(SRC)
ar r $(SNAME) $(OBJ)
ranlib $(SNAME)
DYNAMIC: $(OBJ)
$(CC) -c $(SRC)
$(CC) -shared -o $(DNAME) $(OBJ)
.PHONY: my_printf_static
my_printf_static: $(STATIC)
.PHONY: my_printf_dynamic
my_printf_dynamic: $(DYNAMIC)
.PHONY: all
all: my_printf_static my_printf_dynamic
.PHONY: clean
clean:
$(RM) $(OBJ)
.PHONY: fclean
fclean: clean
$(RM) $(SNAME) $(DNAME)
.PHONY: re
re: fclean all
Thanks!
Your makefile can be boiled down to this:
NAME := libmy_printf_$(shell uname -m)-$(shell uname -s)
SNAME := $(NAME).a
DNAME := $(NAME).so
SRC := $(wildcard src/*.c)
OBJ := $(SRC:.c=.o)
CFLAGS := -ansi -pedantic -Wall -W -Werror -g3 -fPIC
LDFLAGS := -L.
LDLIBS := -l$(...)
.PHONY: all clean fclean re
all: $(SNAME) $(DNAME)
$(SNAME): $(OBJ)
$(AR) $(ARFLAGS) $# $^
$(DNAME): LDFLAGS += -shared
$(DNAME): $(OBJ)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $#
clean:
$(RM) $(OBJ)
fclean: clean
$(RM) $(SNAME) $(DNAME)
re: fclean all
There are multiple things that you should know:
Don't use back-quotes commands, use the $(shell) built-in function in conjunction with the := assignment operator to prevent commands being re-run multiple times (unless this is the desired behavior).
Use only one .PHONY special rule, placed above all rules, and list them there.
Redefining $(CC) or $(RM) variables like you did is pointless since they already contain what you wanted here.
You wrote -l$(NAME) but you didn't define a NAME variable. I change it to $(...) since I couldn't guess what you really wanted here, don't forget to handle this.
Use the name of the targets to be created as the name of the related rules. That way Make won't recreate the targets unless you really want it (by calling the clean, fclean or re rules explicitly).
-L flags and -l flags should not be mixed in the same variable, unless placed at the right place in the linking command. Actually you didn't even used them. I explicitly separated them in the LDFLAGS and LDLIBS built-in variables, as per Make implicit rules.
If you have any questions, go ahead.
As discussed in the comments, if you need to remove the -fPIC flag from the compilation flags for the static library, you should consider building object files in different directories:
EDIT: I added your my_printf_static and my_printf_dynamic rules:
NAME := libmy_printf_$(shell uname -m)-$(shell uname -s)
SNAME := $(NAME).a
DNAME := $(NAME).so
SRC := $(wildcard src/*.c)
SDIR := build-static
SOBJ := $(SRC:src/%.c=$(SDIR)/%.o)
DDIR := build-shared
DOBJ := $(SRC:src/%.c=$(DDIR)/%.o)
CFLAGS := -ansi -pedantic -Wall -Werror -W -g3
LDFLAGS := -L.
LDLIBS := -l$(...)
.PHONY: all clean fclean re my_printf_static my_printf_dynamic
all: my_printf_static my_printf_dynamic
my_printf_static: $(SNAME)
my_printf_dynamic: $(DNAME)
$(SNAME): $(SOBJ)
$(AR) $(ARFLAGS) $# $^
$(DNAME): CFLAGS += -fPIC
$(DNAME): LDFLAGS += -shared
$(DNAME): $(DOBJ)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(SDIR)/%.o: src/%.c | $(SDIR)
$(CC) $(CPPFLAGS) $(CFLAGS) -o $# -c $<
$(DDIR)/%.o: src/%.c | $(DDIR)
$(CC) $(CPPFLAGS) $(CFLAGS) -o $# -c $<
$(SDIR) $(DDIR):
#mkdir $#
clean:
$(RM) -r $(SDIR) $(DDIR)
fclean: clean
$(RM) $(SNAME) $(DNAME)
re: fclean all
What to do so it only creates object files inside the /src directory ?
Don't run the compiler twice. Your STATIC and DYNAMIC rules both depend on $(OBJ), which will cause those files to be built by make's implicit rules. Then, immediately after that you run the compiler again within those rules. Just take those lines out. make normally prints the commands it's going to run, so you should see why it's happening in your build log.
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"
I would like to compile .c files to a .so (shared library).
And I don't understand why, I have that makefile that makes me an error:
LIB = libmy.so
SRC = lib.c
CC = gcc
OBJ = $(CC) -c -fPIC $(SRC)
all: $(LIB)
re: fclean all
$(LIB): $(OBJ)
$(CC) -shared -fPIC $(OBJ) -o $(LIB)
clean:
$(RM) $(OBJ)
fclean: clean
$(RM) $(LIB)
Thanks in advance for helping.
The problem is in the following line:
$(LIB): $(OBJ)
When expanded this becomes:
libmy.so : gcc -c -fPIC lib.c
Hence the error.
What you probably wanted was :
OBJ = lib.o
To save you having to manually convert all .c source files to .o you can use a rule like this instead of OBJ = lib.o:
OBJ = $(SRC:%.c=%.o)
This creates a variable OBJ containing a list of all the files in SRC with any .c extension changed to .o. eg. If we had SRC = foo.c bar.c then the rule above would automatically expand to:
OBJ = foo.o bar.o
$(LIB): $(OBJ)
expands to
libmy.so: gcc -c -fPIC $(SRC)
ie you put your recipe into the depency list, and make rightfully complains.
Personally, I'd write the makefile like this:
CC := gcc
RM := rm -f
LIB := libmy.so
OBJ := lib.o
GARBAGE := $(OBJ)
.PHONY: all clean realclean
all: $(LIB)
$(LIB): LDFLAGS += -shared
$(LIB): $(OBJ)
$(CC) $(LDFLAGS) -o $# $<
$(OBJ): CFLAGS += -fPIC
$(OBJ): %.o : %.c
$(CC) $(CFLAGS) -c -o $# $<
realclean: GARBAGE += $(LIB)
clean realclean:
$(RM) $(GARBAGE)
Note that your original version did not contain a rule to make $(OBJ). If you wanted to use the implicit one, you would need to add -fPIC to CFLAGS.
That works :
LIB = libmy.so
SRC = lib.c
CC = gcc
OBJ = $(SRC:.c=.o)
all: $(LIB)
re: fclean all
$(LIB):
$(CC) -c -fPIC $(SRC)
$(CC) -shared -fPIC $(SRC) -o $(NAME)
clean:
$(RM) $(OBJ)
fclean: clean
$(RM) $(LIB)
I just need OBJ = $(SRC:.c=.o) in fclean
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.