Why isn't the Static Pattern Rule working in my makefile - c

I'm new to Makefiles, so far I've only been doing little projects, but I just did my biggest project with 20 *.c files and put them all in a src file.
With my Makefile I wanted to create an obj file with all the corresponding *.o files and then make them all into an executable. I heard about Static Patterns and I tried to use it on my makefile but I'm probably making a very silly mistake as the output is not what I expected.
My Makefile:
CC=gcc
CFLAGS=-Wall -Wextra -Werror
MLX=mlx/libmlx_Darwin.a
LIBFT=libft/libft.a
I_LIBFT=-Ilibft -Llibft -lft
I_LIBMLX=-Imlx -Lmlx -lmlx
LIB=$(I_LIBFT) $(I_LIBMLX)
COMPATIBILITY=-lX11 -lXext
FRAMEWORK=-framework OpenGL -framework AppKit
HDR=/include/fdf.h
SRC_DIR=/src/
SRCS:=$(wildcard $(SRC_DIR)*.c)
OBJ_DIR=/obj/
OBJS=$(patsubst %.c, $(OBJ_DIR)%.o, $(SRCS))
all: $(LIBFT) app
$(LIBFT):
make -C libft
#echo "done libft"
$(OBJ_DIR):
mkdir $#
$(OBJS): $(OBJ_DIR)%.o: $(SRC_DIR)%.c $(OBJ_DIR)
$(CC) $(CFLAGS) -c $< -o $#
app: $(OBJS)
#echo "making app"
$(CC) $(CFLAGS) $(LIB) $(FRAMEWORK) $(OBJS) -o FdF
clean:
make -C libft $#
fclean: clean
make -C libft $#
re: fclean all
.PHONY: all clean fclean re so
My output:
making app
gcc -Wall -Wextra -Werror -Ilibft -Llibft -lft -Imlx -Lmlx -lmlx -framework OpenGL -framework AppKit -o FdF
Undefined symbols for architecture arm64:
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [app] Error 1
when I expected something like:
gcc -Wall -Wextra -Werror -c file.c -o file.o
gcc -Wall -Wextra -Werror -c file2.c -o file2.o
gcc -Wall -Wextra -Werror -c file3.c -o file3.o
...
gcc -Wall -Wextra -Werror -Ilibft -Llibft -lft -Imlx -Lmlx -lmlx -framework OpenGL -framework AppKit file.o file2.o ... file19.o -o FdF
What am I doing wrong?

I'm pretty sure these are wrong:
HDR=/include/fdf.h
SRC_DIR=/src/
OBJ_DIR=/obj/
Are your source and header files REALLY in a subdirectory of the root of your partition? If you run ls /src/ does it actually show any files?
I suspect that there is nothing there, which means that SRCS is empty because the wildcard expands to no matches, which means OBJS is empty since it's substituting into nothing, which means there are no prerequisites to the app target.

Related

Makefile: fatal error: No such file or directory

There's tons of questions regarding this issue but none have helped... I've tried it all.
I have a
proj.c file I want to compile and it depends on Client_linked_list.h and POOL_check_linked_list.h.
Client_linked_list that depends on nothing but itself
POOL_check_linked_list that depends on Client_linked_list.h
This is my makefile code
CFLAGS =-ansi -Wall -pedantic
CC = gcc
LDFLAGS=-lm
.PHONY: all clean run
all: proj
proj: Client_linked_list.o POOL_check_linked_list.o proj.o
$(CC) $(CFLAGS) $(LDFLAGS) -o proj proj.o Client_linked_list.o POOL_check_linked_list.o
Client_linked_list.o: Client_linked_list.c Client_linked_list.h
$(CC) $(CFLAGS) -c Client_linked_list.c
POOL_check_linked_list.o: POOL_check_linked_list.c POOL_check_linked_list.h Client_linked_list.h
$(CC) $(CFLAGS) -c POOL_check_linked_list.c
proj.o: proj.c Client_linked_list.h POOL_check_linked_list.h
$(CC) $(CFLAGS) -o proj.o -c proj.c
clean:
#echo Cleaning...
rm -f proj Client_linked_list POOL_check_linked_list
This is the error message I'm getting:
gcc -ansi -Wall -pedantic -c Client_linked_list.c
Client_linked_list.c:10:32: fatal error: Client_linked_list.h: No such file or directory
compilation terminated. make: *** [makefile:20:Client_linked_list.o] Error 1
The files are all in the same directory!
You need to use the -I option in your CFLAGS, pointing towards your include folder.
The error seems to come from your compiler which doesn't know where your header file is.

c - Make is only running 'gcc' with no parameters

I'm learning how to use C and Make, but Make is making me tear my hair out. When I run make with all targets I've created it fails, running gcc with no parameters, except one of them randomly works just fine. Here is what happens when I try to build with most of the targets:
$ make strvector.o
gcc
gcc: fatal error: no input files
compilation terminated.
make: *** [vector.o] Error 4
and when I run the one that works:
$ make word.o
gcc -Wall -g -ansi -pedantic -c -o word.o word.c
Here is my makefile:
CC = gcc
CFLAGS = -Wall -g -ansi -pedantic -c -o $# $^
LD = gcc
LDFLAGS =
fw: fw.o vector.o hashtable.o strvector.o
$(LD) $(LDFLAGS) -o fw vector.o hashtable.o strvector.o word.o
fw.o: fw.c vector.o hashtable.o strvector.o word.o
$(CC) $(CFALGS)
vector.o: vector.c word.o
$(CC) $(CFALGS)
hashtable.o: hashtable.c vector.o word.o
$(CC) $(CFLAGS)
word.o: word.c
$(CC) $(CFLAGS)
strvector.o: strvector.c
$(CC) $(CFALGS)
I cannot for the life of me figure out why word.o builds fine but not anything else. If anyone could help that would be much appreciated.
--Edit-- I made a typo. Writing CFALGS instead of CFLAGS. not sure how I missed that one. Thanks guys!
You left out the filenames in the compilation commands.
strvector.o: strvector.c
$(CC) -c $(CFLAGS) -o $# $<
$# gets replaced with the current target, $< is replaced with the current dependency.

Add OpenCL CL/cl.h path to existing Make file

I am trying to successful execute a make file that comes from a new crytpo-coin called Sia Coin. It can be found here Sia Coin GPU Miner. It's relatively new and so some stuff requires more manual installation. I was getting the following error on Ubuntu 16.04 when using the make file. CL/cl.h was missing, and I was able to install and it is located at /usr/include/nvidia-361/CL/cl.h. However, when I ran the make file I still get errors so I think I need to include this path someone in the Make file, the problem is I am not familiar with make files at all. Below is the Make file I need to edit to include the path for compilation:
ifeq ($(shell uname -s),Darwin)
CC ?= clang
LDLIBS += -lcurl -framework OpenCL
else
CC ?= gcc
LDLIBS += -lOpenCL -lcurl
endif
CFLAGS += -c -std=c11 -Wall -pedantic -O2
TARGET = sia-gpu-miner
SOURCES = sia-gpu-miner.c network.c
OBJECTS = $(patsubst %.c,%.o,$(SOURCES))
all: $(TARGET)
%.o: %.c
$(CC) $(CFLAGS) -o $# $<
$(TARGET): $(OBJECTS)
$(CC) -o $# $^ $(LDLIBS)
clean:
rm -f $(TARGET) $(OBJECTS)
.PHONY: all clean
Any help toward solving this problem is greatly appreciated.
Edit:
A new message I am getting now adding
CFLAGS += -c -std=c11 -Wall -pedantic -O2 -I /usr/include/nvidia-361
is now:
-lOpenCL -lcurl /usr/bin/ld: cannot find -lOpenCL collect2: error: ld returned 1 exit status
Two files did compile:
sia-gpu-miner.c
network.c
But I don't know enough to know why the -lOpenCL is not found. No ld directory exists in that directory location in the error if that helps.
Try changing
CFLAGS += -c -std=c11 -Wall -pedantic -O2
to
CFLAGS += -c -std=c11 -Wall -pedantic -O2 -I /usr/include/nvidia-361

What does "linker input file unused because linking not done" mean? (C makefile)

I have created a makefile to compile and link my program, however, I can't figure out why I am getting this error. Is it to do with SDL?
GCC = gcc
CFLAGS = -c -std=c99 -lm -Wall -Wextra -pedantic -O3 -Wfloat-equal -g
SDL = -lSDL2 -lSDL2_ttf -lSDL2_image -lSDL2_mixer
all: ./game
game: global.o display.o player.o entities.o controls.o sound.o menu.o
$(GCC) $(CFLAGS) global.o display.o player.o entities.o controls.o sound.o menu.o -o game
global.o: global.c
$(GCC) $(CFLAGS) $(SDL) global.c
display.o: display.c
$(GCC) $(CFLAGS) $(SDL) display.c
player.o: player.c
$(GCC) $(CFLAGS) $(SDL) player.c
entities.o: entities.c
$(GCC) $(CFLAGS) $(SDL) entities.c
controls.o: controls.c
$(GCC) $(CFLAGS) $(SDL) controls.c
sound.o: sound.c
$(GCC) $(CFLAGS) $(SDL) sound.c
menu.o: menu.c
$(GCC) $(CFLAGS) $(SDL) menu.c
clean:
rm *o game
Your linking command expands to:
gcc -c -std=c99 -lm -Wall -Wextra -pedantic -O3 -Wfloat-equal -g global.o display.o player.o entities.o controls.o sound.o menu.o -o game
which, as you can see, has the -c flag in it. The -c flag tells gcc not to do linking. So it has nothing to actually do. (.o files can only be used for linking, and you've disabled linking, which is why you get that message)
You don't want to use the same flags for compiling and linking. For compiling you probably want -c -std=c99 -Wall -Wextra -pedantic -O3 -Wfloat-equal -g, and for linking you want -lm -lSDL2 -lSDL2_ttf -lSDL2_image -lSDL2_mixer -g.
there are several small oversights in the posted makefile.
Amongst them:
library names are only used during the link step, not the compile step
suggest using the 'wildcard' make operator to get a list of the source files. Then use a patterm replacement operator to get a list of the object files:
for instance:
SRC := $(wildcard *.c)
OBJ := $(SRC:.c=.o)
when a target (all, clean) will not produce a file of the same name, then insert a .PHONY: statement early in the make file:
similarly to:
.PHONY : all clean
the posted make file has no facilities to handle the associated header files, There are several ways to handle that. This follows the OPs lead and does not handle the header files, so changing a header file will not recompile/relink the effected source files.
this line: rm *o game will not remove the name.o files as it is missing the '.' between the root name and the 'o' extension. Also, the '-f' flag should be used with the 'rm' command.
suggest:
rm -f *.o game
this line: all: ./game can create problems
suggest:
all: game
once the list of object files is created (as above) then the compile rules can be reduced:
by using the make operators:
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $# -I.
the -g parameter to the compiler and linker allows for a debugger to be used. If that debugger is gdb then a better parameter is -ggdb
almost always, there is no need to evaluate a macro definition more than once, so rather than using = in a macro definition, use :=
If you want the game to be executable, then insert a chmod command as the last line in the 'link' rule
Suggest reading about the special operators that can be employed in a makefile to help you understand the following, suggested makefile
It is usually best to replace calls to the shell recognized commands with macros.
CC := /user/bin/gcc
RM := /usr/bin/rm
CFLAGS := -c -std=c99 -Wall -Wextra -pedantic -O3 -Wfloat-equal -ggdb
LFLAGS := -std=c99 -O3 -ggdb
SDL := -lSDL2 -lSDL2_ttf -lSDL2_image -lSDL2_mixer
SRC := $(wildcard *.c)
OBJS := $(SRC:.c=.o)
.PHONY : all clean
all: game
game: $(OBJS)
$(CC) $(LFLAGS) $(OBJS) -o $# $(SDL) -lm
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $# -I.
clean:
$(RM) -f *.o game
Do not put -lm or the SDL libraries into CFLAGS, library operands go to the end of the command line. Instead, use an extra variable LDLIBS and modify your game rule like this:
game: global.o display.o player.o entities.o controls.o sound.o menu.o
$(GCC) $(CFLAGS) -o $# global.o display.o player.o entities.o controls.o sound.o menu.o $(LDLIBS)
The -lm operand (it's not an option) and the operands for SDL only apply when linking, thus it should not be part of CFLAGS and should not be specified when compiling without linking (i.e. when -c is supplied).

"make clean" causes "make all" failure

When I execute this Makefile without clean, it functions OK and both the shared library and the main executable are created correctly. However, when I add the clean target, the "make all" fails. What could be the reason?
CC = gcc
CFLAGS = -fPIC -Wall -Werror
LDFLAGS = -shared
TARGET_LIB= libnsd.so
lib: nsd.o nd.o
$(CC) $(LDFLAGS) -o ${TARGET_LIB} nsd.o nd.o -lm
nd.o : nd.c nd.h
$(CC) -c $(CFLAGS) nd.c
nsd.o : nsd.c nsd.h
$(CC) -c $(CFLAGS) nsd.c
all: main.c
$(CC) -o -I. -L. main.c -lnsd
clean:
rm -f libnsd.so nd.o nsd.o
Your all: target needs to depend on the lib target, so the library is built first.
The -o argument to the compiler also needs a name for executable it should create.
all: lib main.c
$(CC) -o main -I. -L. main.c -lnsd
Normally you want the target name to be the file that you create, otherwise things get rebuilt when it's not needed. (the lib: target has the same issue) but as an exampe for the executable:
.PHONY: all
all: lib main
main: lib main.c
$(CC) -o main -I. -L. main.c -lnsd
nos's answer is on the right track.
It only appeared to work before, because you happened to run make in the right order. It won't work after a clean operation because, as nos points out, you have not declared all of your prerequisites. The rule that links main.o must depend on the shared library target, so make knows the right order to build things.
Also, you REALLY want your targets to be the actual file you're building. If they're something else, then make will always think they're out of date even if you haven't changed anything, and always rebuild them.
Something like this will be better:
CC = gcc
CFLAGS = -fPIC -Wall -Werror
CPPFLAGS = -I.
LDFLAGS = -shared
PROGRAM = main
TARGET_LIB= libnsd.so
all: $(PROGRAM)
$(PROGRAM): main.o $(TARGET_LIB)
$(CC) -o $# -L. main.o -lnsd
$(TARGET_LIB): nsd.o nd.o
$(CC) $(LDFLAGS) -o $# nsd.o nd.o -lm
nd.o : nd.c nd.h
nsd.o : nsd.c nsd.h
clean:
rm -f libnsd.so *.o

Resources