Makefile can't find linux/ library - c

I'm attempting to build a loadable kernel module dependent on several source files, but I'm getting this error:
/home/.../Uart.h:3:28: fatal error: linux/spinlock.h: No such file or directory
#include <linux/spinlock.h>
^
The main module code is all in one file (call it "xdev.c"). The dependencies are mostly functions that I need to call in the module and are included by their header files. I have the files organized like this:
./
bin/
This is where I want the compiled dependencies (.o files to go)
src/
My dependencies .c and .h files
...
Uart.h # Error is in this file
Uart.c
Crc8.h
Crc8.c
...
xdev.c # This file include <linux/...> files with no trouble
Makefile
I'm new to using make files, but based on tutorials and questions here, primarily this one, I created this make file:
TARGET = xdev
LINKER = gcc
# None of the compiler or linker flags I have tried worked, so I removed them
LFLAGS =
CFLAGS =
KERN_DIR = /lib/modules/$(shell uname -r)/build/
MOD_SRC = $(shell pwd)
INC_DIR = $(MOD_SRC)/src
SRC_DIR = $(MOD_SRC)/src
BIN_DIR = $(MOD_SRC)/bin
RM = rm -f
SOURCES = $(wildcard $(SRC_DIR)/*.c)
INCLUDES = $(wildcard $(INC_DIR)/*.h)
OBJECTS = $(SOURCES:$(SRC_DIR)/%.c=$(BIN_DIR)/%.o)
$(TARGET): $(OBJECTS)
#$(LINKER) $(OBJECTS) $(LFLAGS) -o $#
$(OBJECTS): $(BIN_DIR)/%.o : $(SRC_DIR)/%.c
#$(CC) $(CFLAGS) -c $< -o $#
obj-m += $(TARGET).o
$(TARGET)-objs := $(OBJECTS)
all:
+make -C $(KERN_DIR) M=$(MOD_SRC) modules
clean:
+make -C $(KERN_DIR) M=$(MOD_SRC) clean
$(RM) $(OBJECTS)
My understanding of what it does is:
make a list of all .c files and the corresponding location for the .o file
OBJECTS = $(SOURCES:$(SRC_DIR)/%.c=$(BIN_DIR)/%.o)
compile the .c files to create the .o files
$(OBJECTS): $(BIN_DIR)/%.o : $(SRC_DIR)/%.c
#$(CC) $(CFLAGS) -c $< -o $#`
link to the .o files so the program knows what the functions defined in the .h files are
$(TARGET): $(OBJECTS)
#$(LINKER) $(OBJECTS) $(LFLAGS) -o $#
add the .o files as objects of the module $(TARGET)-objs := $(OBJECTS)
The command I'm using to make is
sudo make -j4

Try, maybe, to tell your compiler where to look for header files:
$(OBJECTS): $(BIN_DIR)/%.o : $(SRC_DIR)/%.c
#$(CC) $(CFLAGS) -I$(INC_DIR) -I<kernel-folder>/include -c $< -o $#

Related

How to redirect the output of object files to another directory?

I have three directories obj/, inc/ and src/ . The directories inc/ and src/ contains all the .c files. I would like to redirect all the .o files generated in src/ and inc/ to obj/
This is a simple example of my makefile
NAME = push_swap
SRC = $(wildcard ./src/*c)
INC = $(wildcard ./inc/*c)
OBJ1 = $(SRC:.c=.o)
OBJ2 = $(INC:.c=.o)
CC = gcc
CFLAGS = -Wall -Werror -Wextra
$(NAME): $(OBJ1) $(OBJ2)
$(CC) $(CFLAGS) $(OBJ1) $(OBJ2) -o $#
all: $(NAME)
clean:
rm -f */*.o
fclean: clean
rm -f $(NAME)
re: fclean all
The makefile works perfectly, but all the object files are generetad in its src folder, making hard to search for .c files and debbug the code.
By default, Make will build the object file in the directory where it finds the source. If you want the object file to be built somewhere else, there is more than one way to do it.
You could write a rule for Make to use instead of the default:
obj/%.o: src/%.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
And another for source files in inc/, if you want to keep source files there.
Or you could write a more general rule, and use 'vpath` to find the sources:
vpath %.c src inc
obj/%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
EDIT: Did you remember to change the names of the files you ask Make to build (as #MadScientist pointed out in his comment (and as I ought to have pointed out in my Answer))?
Try this:
SRC = $(wildcard ./src/*c)
OBJ1 = $(patsubst ./src/%.c, ./obj/%.o, $(SRC))
CC = gcc
CFLAGS = -Wall -Werror -Wextra
vpath %.c src
obj/%.o: %.c
$(CC) $(CFLAGS) -c -o $# $<
all: $(OBJ1)

Discovering STM32: Writing a makefile to create src inc (etc) directories

I'm an electrical engineer who's gotten into embedded C at a beginner/intermediate level. I've found Geoffery Brown's "Discovering the STM32 Microcontroller" to be an excellent beginner embedded resource after having gone through Steve Oualline's Practical C Programming. I very much recommend that path to anyone wanting to learn embedded C.
To my question: The author of Discovering STM32 provides a Makefile scheme that includes a project-specific Makefile as well as a Makefile common (Makefile.common) to all project directories that gets included. I really want to organize my code into src, inc, obj and bin directories but the author did not provide this functionality in the makefile templates. After reading up on Makefiles and trying a few things out, I'm at a loss as to how to do it with the author-provided structure. My goal is to retain the same Makefile/Makefile.common scheme while having my code be organized into separate bin, src, inc and obj directories within my project subfolder after my .elf is built.
More simply, I want my directory structure / folders to look like :
DiscoveringSTM32
Makefile.common
ProjectA
src
main.c
stuff.c
whateverelse.c
Makefile
inc
stuff.h
whateverelse.h
bin
ProjectA.elf
obj
stuff.o
whateverelse.o
Context / what I'm working with:
FWIW, my full DiscoveringSTM32 repo is here.
The project-specific (e.g. "ProjectA") author provided Makefile looks like this:
TEMPLATEROOT = ..
# compilation flags for gdb
CFLAGS = -O1 -g
ASFLAGS = -g
LDLIBS += -lm
# object files
OBJS = $(STARTUP) main.o
OBJS += foo.o bar.o
OBJS += baz.o fee.o
OBJS += fo.o fum.o
# include common make file
include $(TEMPLATEROOT)/Makefile.common
While the author provided Makefile.common looks like
# name of executable
ELF=$(notdir $(CURDIR)).elf
# Tool path
TOOLROOT="C:\Users\Robert\OneDrive\Documents\GNU_ARM_TOOLS\9-2020-q2-update\bin"
# Library path
LIBROOT="C:\Users\Robert\OneDrive\Documents\DiscoveringSTM32\STM32F10x_StdPeriph_Lib_V3.5.0"
# Tools
CC=$(TOOLROOT)/arm-none-eabi-gcc
LD=$(TOOLROOT)/arm-none-eabi-gcc
AR=$(TOOLROOT)/arm-none-eabi-ar
AS=$(TOOLROOT)/arm-none-eabi-as
# Code Paths
DEVICE=$(LIBROOT)/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x
CORE=$(LIBROOT)/Libraries/CMSIS/CM3/CoreSupport
PERIPH=$(LIBROOT)/Libraries/STM32F10x_StdPeriph_Driver
# Search path for standard files
vpath %.c $(TEMPLATEROOT)
# Search path for perpheral library
vpath %.c $(CORE)
vpath %.c $(PERIPH)/src
vpath %.c $(DEVICE)
# Search path for Library
vpath %.c $(TEMPLATEROOT)/Library/ff9/src
vpath %.c $(TEMPLATEROOT)/Library/ff9/src/option
vpath %.c $(TEMPLATEROOT)/Library
# Processor specific
#PTYPE = STM32F10X_MD_VL
PTYPE = STM32F10X_MD #try this for blue pill
LDSCRIPT = $(TEMPLATEROOT)/stm32f100.ld
STARTUP= startup_stm32f10x.o system_stm32f10x.o
# Compilation Flags
FULLASSERT = -DUSE_FULL_ASSERT
LDFLAGS+= -T$(LDSCRIPT) -mthumb -mcpu=cortex-m3
CFLAGS+= -mcpu=cortex-m3 -mthumb
CFLAGS+= -I$(TEMPLATEROOT) -I$(DEVICE) -I$(CORE) -I$(PERIPH)/inc -I.
CFLAGS+= -D$(PTYPE) -DUSE_STDPERIPH_DRIVER $(FULLASSERT)
CFLAGS+= -I$(TEMPLATEROOT)/Library/ff9/src -I$(TEMPLATEROOT)/Library
# Build executable
$(ELF) : $(OBJS)
$(LD) $(LDFLAGS) -o $# $(OBJS) $(LDLIBS)
# compile and generate dependency info
%.o: %.c
$(CC) -c $(CFLAGS) $< -o $#
$(CC) -MM $(CFLAGS) $< > $*.d
%.o: %.s
$(CC) -c $(CFLAGS) $< -o $#
clean:
rm -f $(OBJS) $(OBJS:.o=.d) $(ELF) startup_stm32f* $(CLEANOTHER)
debug: $(ELF)
arm-none-eabi-gdb $(ELF)
# pull in dependencies
-include $(OBJS:.o=.d)
I think I understand the jist of what's going on here where we define our object files (i.e. main.o from main.c, foo.o from foo.c) and we have rules to create the object files from their dependencies, ultimately building my flashable ELF file.
Things I've tried
After some googling and reading some online tutorials I've tried defining my directories like so:
BINDIR = bin
SRCDIR = src
OBJDIR = obj
INCDIR = inc
and then wildcarding all my .c's and .o's
# name of executable
ELF:= $(BINDIR)/$(notdir $(CURDIR)).elf
SRC := $(wildcard $(SRCDIR)/*.c)
OBJ = $(SRC:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
OBJ += $(STARTUP)
I +='d in $(STARTUP) and thus the associated files defined by STARTUP as I've run into "error: no rule to make target startup_stm32f10x.o".
The farthest I've got with this endeavor is successfully creating a bin directory with the .elf file in it in my specific project directory (e.g. Documents/DiscoveringStm32/projectA). Getting there involved keeping the author-provided += object file scheme and modifying the ELF definition in makefile.common to be:
ELF:= $(BINDIR)/$(notdir $(CURDIR)).elf
I tried doing:
$(ELF) : $(OBJDIR)/$(OBJS)
$(LD) $(LDFLAGS) -o $# $(OBJS) $(LDLIBS)
# compile and generate dependency info
$(OBJDIR)/%.o: $(SRCDIR)/%.c
$(CC) -c $(CFLAGS) $< -o $#
$(CC) -MM $(CFLAGS) $< > $*.d
%.o: %.s
$(CC) -c $(CFLAGS) $< -o $#
but this threw errors.
I've come to have an appreciation for the complexities of Makefiles through all this. I'm sure I'll have learned quite a bit more about writing them once this is figured out.
Thanks for the help in advance!
In order to allow the source files to reside in src, you can use VPATH = $(SRCDIR) along with your definition of SRCDIR.
To place the object files in obj, you have to add the directory to the filenames in OBJS, e. g. with OBJS := $(OBJS:%.o=$(OBJDIR)/%.o).
The compile rule head is then $(OBJDIR)/%.o: %.c.

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: no rule to make target

I'm following this guide about makefile, but I didn't understand at all the last example and I can't get my makefile work, as I obtain the error make: *** No rule to make target "obj/date.o", needed by "Whatsapp". Stop.
Here is my makefile:
IDIR = ../include
CC = gcc
CFLAGS = -I$(IDIR)
ODIR = obj
LDIR = ../lib
LIBS = -lncurses
# Keep the alphabetical order!
_DEPS = \
constants.h\
date.h\
inOut.h\
languages.h\
message.h\
mycurses.h\
mysocket.h\
text.h\
time.h\
user.h\
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
# Keep the alphabetical order!
_OBJ = \
date.o\
inOut.o\
languages.o\
main.o\
message.o\
mycurses.o\
mysocket.o\
text.o\
time.o\
user.o\
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
# these two lines should tell the compilator that my .o files depend by .c files, don't they?
$(ODIR)/%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
Whatsapp: $(OBJ)
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
.PHONY: clean
clean:
rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~
Obviously, all my *.c are in the current folder, so really I don't know what I am missing.
Just for more clarity, here is the content of the current folder:
urbijr#urbijr-VirtualBox:/media/sf_Whatsapp_CLIENT$ ls
constants.h indexbook.txt languages.c makefile message.h mycurses.h text.c time.h
date.c inOut.c languages.h message.c message.txt mysocket.c text.h user.c
date.h inOut.h main.c message_for_user.txt mycurses.c mysocket.h time.c user.h
Your dependencies are not as you have specified in your makefile. The line below specifies that all include files should be in the directory $(IDIR).
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
This is set as ../include, but it seems you have all the header files in the same directory. Either move them to ../include or change IDIR to . (the current directory).
You'll also need to create the output directory (obj) as make won't do this automatically.

How to create reference to an .o file in Makefile

I was given two .o files with corresponding .h files to use for an assignment, but I do not know how to get the compiler to use the .o files. This is the Makefile I am currently using:
TARGET = prog
LIBS = -lm
CC = gcc
CFLAGS = -g -Wall
.PHONY: default all clean
default: $(TARGET)
all: default
OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))
HEADERS = $(wildcard *.h)
%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) -c $< -o $#
.PRECIOUS: $(TARGET) $(OBJECTS)
$(TARGET): $(OBJECTS)
$(CC) $(OBJECTS) -Wall $(LIBS) -o $#
clean:
-rm -f *.o
-rm -f $(TARGET)
I believe I need to add the file1.o and file2.o at the end, but I am not sure if that is right. I do have the .h files in the C source files when appropriate, so the only reason that I can think of for the compilation error is that the .o files are not being compiled with my code.
Add a define for the provided .o's (e.g.):
PREBUILT_O = fludger.o ramble.o plexor.o
Change your target rule to:
$(TARGET): $(OBJECTS) $(PREBUILT_O)
$(CC) $(OBJECTS) $(PREBUILT_O) $(LIBS) -o $#
The compiler doesn't use your .o files. The linker does.
Your link step needs to be
$(TARGET) : $(OBJECTS)
$(LD) $(OBJECTS) $(LIBS) -o $#
(Very possibly missing some other linker flags, but that's the crux of your problem)
Also, you probably don't want the clean step to delete all the .o files since you're provided with at least two of them.

Resources