VScode fails to recognize include path from Makefile - c

Bellow is my Makefile from which vscode should understand that the #include "philo.h" and #include "philo_bonus.h" are okay even though those .h files are not in the same folders (srcs and srcs_bonus) as my .c, thanks to the -I include/.
What is very weird is that it behaves in the expected way for my srcs/ files but no for my srcs_bonus/ files which give me the error : cannot open source file "philo_bonus.h"
It does compile well so i assume the issue is vscode's. I have tried reloading the window several times with no differences and this issue has come up accross different projects. Is this a glitch or am I missing something here ?
SRCS = philo.c \
thread.c \
util.c \
lib.c \
free.c \
init.c \
SRCS_BONUS = philo_bonus.c \
thread_bonus.c \
util_bonus.c \
lib_bonus.c \
free_bonus.c \
init_bonus.c \
OBJS = $(addprefix srcs/, $(SRCS:.c=.o))
OBJS_BONUS = $(addprefix srcs_bonus/, $(SRCS_BONUS:.c=.o))
INC = -I include/
CC = cc -pthread
AR = ar rcs
CFLAGS = -g3 -Wall -Wextra -Werror -fsanitize=address
RM = rm -f
NAME = philo
%.o: %.c
$(CC) $(CFLAGS) $(INC) -c $< -o $#
$(NAME): $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o $(NAME)
all: $(NAME)
bonus: $(OBJS_BONUS)
$(CC) $(CFLAGS) $(OBJS_BONUS) -o $(NAME)
clean:
$(RM) $(OBJS) $(OBJS_BONUS)
fclean: clean
$(RM) $(NAME)
re: fclean all
.PHONY: all bonus clean fclean re
Here is my file tree :
include/
├─ philo.h
├─ philo_bonus.h
srcs/
├─ files.c
srcs_bonus/
├─ files_bonus.c
Makefile
I am on Ubuntu 22.04.1

Related

Is there a way to have all my object files in the same directory using Make?

So, I decided to learn make as my first step into large projects, and I have to say that it is not that hard if you are just doing simple tasks and got addicted to it.
However I usually work with a scheme for my directories:
.
├── build
├── include
│   └── func.h
├── lib
│   └── func.c
├── Makefile
└── src
└── main.c
I usually have all my object files spread in the build directory. However, I could only map the source files to the build folder (like ./build/src/main.o where I prefer ./build/main.o).
I Tried Reading The Documentation to no avail!
this is what I came up with so far:
# C Compiler
CC = gcc
#------------- Directories
SOURCE_DIR = src lib
OBJECTS_DIR = build
INCLUDE_DIR = . ./include
#----------------------------
VPATH = $(SOURCE_DIR)
#------------- Files
SOURCE = $(foreach dir, $(SOURCE_DIR), $(wildcard $(dir)/*.c))
# Fake Objects (Just so I can map them to c files)
FOBJECTS = $(addprefix $(OBJECTS_DIR)/, $(SOURCE:.c=.o))
OBJECTS = $(addprefix $(OBJECTS_DIR)/, $(notdir $(FOBJECTS)))
DEPS = $(foreach dir, $(INCLUDE_DIR), $(wildcard $(dir)/*.h))
#----------------------------
#------------- Flags
OPT = -O0
IFLAGS = $(foreach dir, $(INCLUDE_DIR), -I$(dir))
LFLAGS = -lm
CFLAGS = -Wall
FLAGS = $(OPT) $(IFLAGS) $(LFLAGS) $(CFLAGS)
#----------------------------
BINARY = bin
all : $(BINARY)
$(BINARY) : $(OBJECTS)
$(CC) -o $# $(OBJECTS)
$(OBJECTS) : $(FOBJECTS)
mv -t $(OBJECTS_DIR) $(FOBJECTS)
rm -rf -- $(OBJECTS_DIR)/*/
$(OBJECTS_DIR)/%.o : %.c $(DEPS)
$(CC) $(FLAGS) -c -o $# $<
exec : $(BINARY)
#./$(BINARY)
clean :
rm -rf $(OBJECTS) $(BINARY)
I keep getting this error:
gcc -O0 -I. -I./include -lm -Wall -c -o build/src/main.o src/main.c
Assembler messages:
Fatal error: can't create build/src/main.o: No such file or directory
make: *** [Makefile:39: build/src/main.o] Error 1
I know the reason is the Fake Objects I created but creating the perfect rule for this is hard
As I said, you probably do not want to put all .o in the same directory because comingling .o files from unrelated projects isn't the best organization. If the .o files were related, you'd probably put the .c files in the same subdir.
But, if you did want all .o in a single build directory, one way is to create the build/* subdirs:
# C Compiler
CC = gcc
#------------- Directories
SOURCE_DIR = src lib
OBJECTS_DIR = build
INCLUDE_DIR = . ./include
OBJ_MK = $(addprefix $(OBJECTS_DIR)/, $(SOURCE_DIR))
#----------------------------
VPATH = $(SOURCE_DIR)
#------------- Files
SOURCE = $(foreach dir, $(SOURCE_DIR), $(wildcard $(dir)/*.c))
# Fake Objects (Just so I can map them to c files)
FOBJECTS = $(addprefix $(OBJECTS_DIR)/, $(SOURCE:.c=.o))
OBJECTS = $(addprefix $(OBJECTS_DIR)/, $(notdir $(FOBJECTS)))
DEPS = $(foreach dir, $(INCLUDE_DIR), $(wildcard $(dir)/*.h))
#----------------------------
#------------- Flags
OPT = -O0
IFLAGS = $(foreach dir, $(INCLUDE_DIR), -I$(dir))
LFLAGS = -lm
CFLAGS = -Wall
FLAGS = $(OPT) $(IFLAGS) $(LFLAGS) $(CFLAGS)
#----------------------------
BINARY = bin
all : $(OBJ_MK) $(BINARY)
$(BINARY) : $(OBJECTS)
$(CC) -o $# $(OBJECTS)
$(OBJECTS) : $(FOBJECTS)
mv -t $(OBJECTS_DIR) $(FOBJECTS)
rm -rf -- $(OBJECTS_DIR)/*/
$(OBJECTS_DIR)/%.o : %.c $(DEPS)
$(CC) $(FLAGS) -c -o $# $<
exec : $(BINARY)
#./$(BINARY)
clean :
rm -rf $(OBJECTS) $(BINARY)
rm -rf $(OBJ_MK)
$(OBJ_MK):
mkdir $#
The make output is:
mkdir build/src
mkdir build/lib
gcc -O0 -I. -I./include -lm -Wall -c -o build/src/main.o src/main.c
gcc -O0 -I. -I./include -lm -Wall -c -o build/lib/func.o lib/func.c
mv -t build build/src/main.o build/lib/func.o
rm -rf -- build/*/
gcc -o bin build/main.o build/func.o
However, the above actually makes the build more complex because its "natural" tendency was to create the subdirs. To override that required extra mv and rm commands.
To use the subdirectory method, the build is actually simpler, and we can do:
# C Compiler
CC = gcc
#------------- Directories
SOURCE_DIR = src lib
OBJECTS_DIR = build
INCLUDE_DIR = . ./include
OBJ_MK = $(addprefix $(OBJECTS_DIR)/, $(SOURCE_DIR))
#----------------------------
VPATH = $(SOURCE_DIR)
#------------- Files
SOURCE = $(foreach dir, $(SOURCE_DIR), $(wildcard $(dir)/*.c))
# Fake Objects (Just so I can map them to c files)
OBJECTS = $(addprefix $(OBJECTS_DIR)/, $(SOURCE:.c=.o))
DEPS = $(foreach dir, $(INCLUDE_DIR), $(wildcard $(dir)/*.h))
#----------------------------
#------------- Flags
OPT = -O0
IFLAGS = $(foreach dir, $(INCLUDE_DIR), -I$(dir))
LFLAGS = -lm
CFLAGS = -Wall
FLAGS = $(OPT) $(IFLAGS) $(LFLAGS) $(CFLAGS)
#----------------------------
BINARY = bin
all : $(OBJ_MK) $(BINARY)
$(BINARY) : $(OBJECTS)
$(CC) -o $# $(OBJECTS)
$(OBJECTS_DIR)/%.o : %.c $(DEPS)
$(CC) $(FLAGS) -c -o $# $<
exec : $(BINARY)
#./$(BINARY)
clean :
rm -rf $(OBJECTS) $(BINARY)
rm -rf $(OBJ_MK)
$(OBJ_MK):
mkdir $#
The make output is:
mkdir build/src
mkdir build/lib
gcc -O0 -I. -I./include -lm -Wall -c -o build/src/main.o src/main.c
gcc -O0 -I. -I./include -lm -Wall -c -o build/lib/func.o lib/func.c
gcc -o bin build/src/main.o build/lib/func.o
If you really want all the objects in a single directory, you almost have it right but you added some very strange rules that I don't understand; what is this for:
$(OBJECTS) : $(FOBJECTS)
mv -t $(OBJECTS_DIR) $(FOBJECTS)
rm -rf -- $(OBJECTS_DIR)/*/
? This is what's causing your problem. You're saying that every individual object file depends on all the "intermediate" object files, so then make tries to build these "intermediate" object files. The only way it knows to do that is with the pattern rule you provided, but that doesn't build those files.
Remove that rule altogether and it will probably work. You just want:
VPATH = $(SOURCE_DIR)
OBJECTS = $(addprefix $(OBJECTS_DIR)/, $(notdir $(SOURCE:.c=.o)))
all : $(BINARY)
$(BINARY) : $(OBJECTS)
$(CC) -o $# $(OBJECTS)
$(OBJECTS_DIR)/%.o : %.c $(DEPS)
$(CC) $(FLAGS) -c -o $# $<
etc. The compiler will build the object files directly into their final destination. You don't need the FOBJECTS thing or the rule that uses it.

Makefile: Separated sources and objects

I've been trying for some time to separate the source files of my project from the generated object files.
Indeed, I would like my project to be structured this way:
obj/
main.o
src1.o
[...]
src/
main.c
src1.c
[...]
Makefile
The Makefile I currently have is as follows:
NAME = a.out
OBJ_DIR = "obj"
SRC_DIR = "src"
MAIN_SRC = main.c
PROJ_SRC = src1.c \
src2.c \
src3.c
MAIN_OBJ = $(MAIN_SRC:%.c=%.o)
PROJ_OBJ = $(PROJ_SRC:%.c=%.o)
CC = gcc
RM = rm -rf
$(NAME): $(MAIN_OBJ) $(PROJ_OBJ)
$(CC) $(MAIN_OBJ) $(PROJ_OBJ) -o $(NAME)
all: $(NAME)
clean:
$(RM) $(MAIN_OBJ) $(PROJ_OBJ)
fclean: clean
$(RM) $(NAME)
I tried to use pattern rules, without success.
MAIN_OBJ = $(MAIN_SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
PROJ_OBJ = $(PROJ_SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
[...]
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(CFLAGS) -c $< -o $#
Does anyone have a solution to my problem?
MAIN_SRC and PROJ_OBJ do not have directory prefix, so that expressions
$(MAIN_SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
$(PROJ_SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
do not replace anything.
Fix:
MAIN_OBJ := $(MAIN_SRC:%.c=$(OBJ_DIR)/%.o)
PROJ_OBJ := $(PROJ_SRC:%.c=$(OBJ_DIR)/%.o)
And then your pattern rule should work.
You may like to have make create that $(OBJ_DIR) for you:
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
$(CC) $(CFLAGS) -c -o $# $<
$(OBJ_DIR) :
mkdir -p $#
A more advanced example for you with automatic header dependency generation.
bro!
If your project "main" 's architecture is just liking this:
main
|
|__Makefile
|__obj
|__src
|__main.c
|__src1.c
|__src2.c
[...]
Just add this to your "Makefile" to store your object out of source files directory:
# Object files
# String substituion for every C/C++ file
# e.g: ./src/src1.cpp turns into ./obj/src1.o
OBJS := $(patsubst %.c, ${OBJ_DIR}/%.o, $(notdir $(SRC_DIR)))
And just add this to your "Makefile" to compile:
# Compile: Generate object files from source files
# $# := {NAME}
# $< := THE first file
# $^ all the dependency
# C Sources
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(C_FLAGS) -c $< -o $#
END!

Makefile optimization for quickly compiling a library as quickly as possible?

Are there any methods I can use to shave seconds off my library's compilation?
My old Makefile took 1.86s to run, up to 5.147 total.
After I changed
%.o: %.c
$(CC) $(FLAGS) -c -o $# $<
Into:
#$(CC) $(FLAGS) -c $(OBJ:.o=.c)
And added # to silence all the output, my new Makefile took 1.40s to run, up to 3.481 s total.
I'm wondering if there's any ways I can optimize my makefile to simply make it run faster or make it more "useful"? Where do I go to learn about micro-adjustments to get a slightly faster compiled program?
https://github.com/Hourai42/libft/blob/master/Makefile
NAME = libft.a
FLAGS = -Wall -Wextra -Werror
CC = gcc
OBJ = ft_strrchr.o ft_putstr.o ft_strcmp.o ft_strlcat.o ft_memcpy.o \
ft_strequm.o ft_memmove.o ft_strsplit.o ft_strncpy.o ft_lstmap.o \
ft_lstadd.o ft_striter.o ft_strstr.o ft_isdigit.o ft_putnbr.o \
ft_memccpy.o ft_strdel.o ft_nmbwrd.o ft_memchr.o ft_bzero.o \
ft_isalnum.o ft_putstr_fd.o ft_lstiter.o ft_lstdelone.o ft_toupper.o
\
ft_strcpy.o ft_lstnew.o ft_strdup.o ft_putnbr_fd.o ft_striteri.o \
ft_strmap.o ft_putendl_fd.o ft_memdel.o ft_strnstr.o ft_putchar.o \
ft_isascii.o ft_strlen.o ft_strsub.o ft_strnew.o ft_memalloc.o
ft_putendl.o \
ft_strncat.o ft_itoa.o ft_strncmp.o ft_memcmp.o ft_strtrim.o
ft_strequ.o
\
ft_putchar_fd.o ft_memset.o ft_isalpha.o ft_strcat.o ft_tolower.o \
ft_strnequ.o ft_strjoin.o ft_atoi.o ft_strclr.o ft_strmapi.o \
ft_isprint.o ft_lstdel.o ft_strchr.o ft_mallocwrd.o ft_countplace.o \
ft_isprime.o ft_hassqrt.o ft_fibonacci.o ft_recursive_power.o \
ft_recursive_factorial.o
all: $(NAME)
$(NAME):
#$(CC) $(FLAGS) -c $(OBJ:.o=.c)
#ar rc $(NAME) $(OBJ)
#ranlib $(NAME)
clean:
#/bin/rm -f $(OBJ)
fclean: clean
#/bin/rm -f $(NAME)
re: fclean all
.PHONY: clean fclean re
Redo only what needs to (huge improvement).
Use parallel make (significant improvement if run on a multicore CPU).
Invoke only one single shell per recipe (moderate to minor improvement).
Example:
NAME = libft.a
FLAGS = -Wall -Wextra -Werror
CC = gcc
SRCS = $(wildcard *.c)
OBJS = $(patsubst %.c,%.o,$(SRCS))
.PHONY: all clean ultraclean
all: $(NAME)
%.o: %.c
#$(CC) $(FLAGS) -c -o $# $<
$(NAME): $(OBJS)
#ar rc $(NAME) $^ && \
ranlib $(NAME)
clean:
#/bin/rm -f $(OBJS)
ultraclean:
#/bin/rm -f $(OBJS) $(NAME)
And then, if you have, let's say, 6 cores and hyper-threading:
$ make -j12
Note: of course, with parallel make, do not parallelize cleaning targets (clean, ultraclean) and building targets (all), as you do with your re target.

How to create make file for only object and header file?

I'm performing blackbox testing using a set.h interface where I have no access to set.c, I've been provided with the object file set.o and I'm required to write a bunch of tests in a main.c file for the set. How do I create a makefile that would include set.o, set.h and main.c?
**I already have the set.o file so I don't have to regenerate it using set.c
I'm confused because I only know how to do this using the complete files.
Here's my template
CC = clang
CFLAGS = -g -Wall
PROG = example
HDRS = set.h
SRCS = main.c
OBJDIR = object
OBJS = $(OBJDIR)/main.o $(OBJDIR)/set.o
# compiling rules
$(PROG): $(OBJS) $(OBJDIR)
$(CC) $(CFLAGS) $(OBJS) -o $(PROG)
$(OBJDIR)/set.o: set.h $(HDRS) $(OBJDIR)
$(CC) $(CFLAGS) -c set.h -o $(OBJDIR)/set.o
$(OBJDIR)/main.o: main.c $(HDRS) $(OBJDIR)
$(CC) $(CFLAGS) -c main.c -o $(OBJDIR)/main.o
$(OBJDIR):
mkdir $(OBJDIR)
clean:
rm -f $(PROG) $(OBJS)
If you already have the set.o file there is no need to create a rule for it, just use it. Also note I got rid of the mkdir because if you already have a set.o, it should already be in objects/ right?
CC = clang
CFLAGS = -g -Wall
PROG = example
HDRS = set.h
SRCS = main.c
OBJDIR = object
OBJS = $(OBJDIR)/main.o
# compiling rules
$(PROG): $(OBJS)
$(CC) $(CFLAGS) $(OBJS) $(OBJDIR)/set.o -o $(PROG)
$(OBJDIR)/main.o: main.c $(HDRS)
$(CC) $(CFLAGS) -c main.c -o $(OBJDIR)/main.o
clean:
rm -f $(PROG) $(OBJS)

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.

Resources