Makefile C subdirectory rule to make obj - c

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.

Related

"clang: error: cannot specify -o when generating multiple output files" fix

I'm trying to compile my C project using clang (I'm on MacOS Monterry) and a Makefile, but I keep getting the same error from clang in the command line:
> make
gcc -c src/ji.c src/main.c -o src/ji.o
clang: error: cannot specify -o when generating multiple output files
make: *** [src/ji.o] Error 1
These are the only files I have in the project so far:
src/main.c
src/ji.c
include/ji.h
The Makefile looks like this:
cc = gcc
src = $(wildcard src/*.c)
obj = $(src:.c=.o)
exec = ji
$(exec): $(obj)
$(cc) -Iinclude $< -o build/$#
%.o: %.c
$(cc) -c $(src) -o $#
clean:
-rm src/*.o
-rm ji
From YouTube videos I've seen, this should be the ideal Makefile for the project but no matter what I change I get the error.
There are a few issues:
-Iinclude needs to be on the %.o: %.c rule command
In %.o: %.c, we don't want $(src) but rather $<
We want patsubst to get the .o list obj
The $(exec) target doesn't match the -o option
The clean doesn't match the placement of the executable
Here's a refactored version (e.g. one way to do this--there are others):
cc = gcc
src = $(wildcard src/*.c)
obj = $(patsubst %.c,%.o,$(src))
exec = build/ji
$(exec): $(obj)
mkdir -p build
$(cc) $^ -o $#
%.o: %.c
$(cc) -c $< -o $# -Iinclude
clean:
rm -f src/*.o
rm -fr build
Here's the output of make:
gcc -c src/ji.c -o src/ji.o -Iinclude
gcc -c src/main.c -o src/main.o -Iinclude
mkdir -p build
gcc src/ji.o src/main.o -o build/ji
Here's the output of make clean:
rm -f src/*.o
rm -fr build

Issue when linking with `-lrt` on Mac OSX

On my Mac OSX 10.13, I always use the following makefile to compile C codes:
TARGET = run
LIBS = -O2 -lm -lrt
CC = gcc
.PHONY: default all clean
all: $(TARGET)
OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))
HEADERS = $(wildcard *.h)
%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) -c $< -o $#
.PRECIOUS: $(TARGET) $(OBJECTS)
$(TARGET): $(OBJECTS)
$(CC) $(OBJECTS) $(CFLAGS) $(LIBS) -o $#
clean:
-rm -f *.o
-rm -f $(TARGET)
Note that I use -lrt on purpose because I use #include <aio.h> for some of my codes. Because of that, I keep getting this error:
ld: library not found for -lrt
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [run] Error 1
This error does not show up when running on Linux systems. How do I fix that to be runnable on Mac OSX?

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)

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"

C- Makefile for the entire folder

I have been using a makefile for my c++ projects. However I tried to convert it into C and tried to compile with gcc and getting a such error: make: *** No rule to make target*.o', needed by microc'. Stop.
This is my makefile:
CC=gcc
CFLAGS=-c -std=gnu99 -Wall -pedantic
LDFLAGS=
SOURCES=*.c
OBJECTS=$(SOURCES:.c=.o)
EXECUTABLE=microc
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.c.o:
$(CC) $(CFLAGS) $< -o $#
clean:
rm -rf *o microc
You can't use SOURCES=*.c. That just sets the variable to the string *.c, so OBJECTS is the string *.o. You want (assuming you're using GNU make):
SOURCES := $(wildcard *.c)

Resources