Makefile auto-dependency generation - linux

I am trying to see auto generated dependency the makefile is below:
OBJS := main.o
run : $(OBJS)
$(CC) $(OBJS) -o run -lstdc++
-include $(OBJS:.o=.d)
%.o : %.cpp
$(CC) -c $(CFLAGS) $*.cpp -o $*.o
%.d : %.cpp
#set -e; rm -f $#; \
$(CC) -M $(CPPFLAGS) $< > $#.$$$$; \
echo "creating dependency file."; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
# remove compilation products
clean :
rm -f run *.o *.d*
But the makefile generate a huge list of dependency in main.d but the actual needed is the first few lines. So where I am getting wrong?

Try this instead:
OBJS := main.o
run : $(OBJS)
$(CC) $(OBJS) -o run -lstdc++
-include $(OBJS:.o=.d)
%.o : %.cpp
$(CC) -c -MMD -MP $(CFLAGS) $*.cpp -o $*.o
# remove compilation products
clean :
rm -f run *.o *.d*

Related

How to link libraries on Raspberry Pi cross compiler?

I followed this guide to build a cross compiler for Raspberry Pi ARMv7. It works fine (compiles ok hello world) but the problem is I can't use Raspberry Pi libraries such as wiringpi, sqlite etc.
This is my Makefile.
CC = /opt/cross-pi-gcc/bin/arm-linux-gnueabihf-g++
QUOTE := "
CFLAGS = -g -lwiringPi -pthread -lpthread
PROGRAM = lora
OBJDIR = obj
CPP_SRCS += \
src/main.cpp \
src/radio/sx1276/sx1276.cpp \
src/radio/radio.cpp \
OBJ_FILES += \
$(OBJDIR)/main.o \
$(OBJDIR)/sx1276.o \
$(OBJDIR)/radio.o \
all: make_dir $(OBJ_FILES)
$(CC) $(OBJ_FILES) $(CFLAGS) -o $(PROGRAM)
make_dir:
mkdir -p $(OBJDIR)
$(OBJDIR)/main.o: src/main.cpp
$(CC) $(CFLAGS) -c -o $# $<
$(OBJDIR)/service.o: src/service/service.cpp
$(CC) $(CFLAGS) -c -o $# $<
$(OBJDIR)/sx1276.o: src/radio/sx1276/sx1276.cpp
$(CC) $(CFLAGS) -c -o $# $<
$(OBJDIR)/radio.o: src/radio/radio.cpp
$(CC) $(CFLAGS) -c -o $# $<
clean:
rm $(PROGRAM)
rm -rf $(OBJDIR)
The error I'm getting:
/opt/cross-pi-gcc/lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ld: cannot find -lwiringPi
I copied some libraries from my Pi into a folder on my home dir with this command.
rsync -vR --progress -rl --delete-after --safe-links pi#192.168.1.PI:/{lib,usr,opt/vc/lib} $HOME/raspberrypi/rootfs
Which I found it here.
But I'm not sure how to link them. Did I overlook something?
Note: The piece of code I'm trying to compile was compiling fine on Windows's cross-compiler.
I'm trying to setup a tool-chain on my Linux desktop. I'm using Manjaro.
You have to tell the linker where to look for the libraries.
You can add the flag -L$HOME/raspberrypi/rootfs/usr/lib, or wherever libwiringPi.so is located.
You have to point the compiler to the right headers as well. For that you use the -I flag. E.g. -I$HOME/raspberrypi/rootfs/usr/include. This goes in the CFLAGS of the targets that include wiringPi.h.
Also, -lwiringPi -pthread -lpthread don't belong in the CFLAGS, they are linker flags. You only need them in the target that builds PROGRAM. You could add a separate variable LDFLAGS, for example.

Makefile : How to specify where to generate an object

I would like to specify a repository for an object I generate in my makefile.
I searched for a while but only found elaborate solutions, for a list of objects, while I would like to TARGET ONE OBJECT ONLY.
(makefile is new for me, so the simpler the better)
Here is my code:
///////////////////////////////////
*definition of several directories*
*definition of CC, CFLAGS, CInclude*
cutgen:
$(CC) $(CFlags) -D__LINUX__ $(CDir)cutgen.c -o cutgen
check: cutgen cutcheck.c *list of objects here*
$(CC) $(CFlags) -I $(CHeaderDir) cutcheck.c *list of objects here* -o cutcheck
./cutcheck
cutcheck.c: cutgen test.o
./cutgen $(CDir)test.c -o cutcheck.c
test.o: util.o
$(CC) $(CFlags) -c $(CInclude) $(CDir)test.c
util.o: config.o
$(CC) $(CFlags) -c $(CInclude) $(GenDir)util.c
...
...
stubs.o:
$(CC) $(CFlags) $(CInclude) -c $(StubsDir)stubs.c
clean:
rm -f *.o *~ cutcheck* cutgen
all: check
///////////////////////////////////
Here for example, I would like to generate util.o in the Objects folder.
Any help would be appreciated, thank you in advance !
$(Objects)/util.o: config.o
$(CC) $(CFlags) -c $(CInclude) $(GenDir)util.c -o $#
(And are you sure about that prerequisite? I think $(GenDir)util.c might be better than config.o.)

Undefined reference error while compiling

I'm trying to compile a project that has multiple *.c files and *.h file when I type the following command:
$gcc -c -I ../hdr main.c gestic.c menu.c
the hdr folder is where the *.h files are located, the .o files are created but when I try to link them using the command:
$gcc -o main.o gestic.o menu.o
I see errors
gestic.c:(.text+0x..): undefined reference to functions that are declared in *.h files
$gcc -Wall -c -I../hdr -o main.o main.c
$gcc -Wall -c -I../hdr -o menu.o menu.c
$gcc -Wall -c -I../hdr -o gestic.o gestic.c
$gcc -Wall -o myprogram main.o menu.o gestic.o
Using a Makefile is very common for this task
example (untested) Makefile:
CC=gcc
CFLAGS=-Wall -I../hdr
all: myprogram
myprogram: main.o menu.o gestic.o
$(CC) -o $# $^
gestic.o: gestic.c
$(CC) $(CFLAGS) -c -o $# $<
main.o: main.c
$(CC) $(CFLAGS) -c -o $# $<
menu.o: menu.c
$(CC) $(CFLAGS) -c -o $# $<
Try:
$ gcc main.o gestic.o menu.o
-o filename: Place output in filename
Firstly header files are not included, secondly you might use the function that doesn't contain the definition.
The message undefined reference to 'function_name' implies that of all the object files you're giving to the linker, none of them has a definition for function_name. That means that either
You're not linking with *.o
*.c (as compiled) does not contain a definition for function_name -- by 'as compiled' I mean with all of the various preprocessor options you use on it.
here -Iinclude/
try,
gcc -c file.c -I<include_dir>
If you compile more files better to have makefile to create the objects of those files, link those objects along with header.
Sample makefile,
CC = gcc
CFLAGS = -Wall
INCLUDE = sample.h
OBJ = samople1.o sample2.o
%.o: %.c $(INCLUDE)
$(CC) $(CFLAGS) -c -o $# $<
go: $(OBJ)
gcc $(CFLAGS) -o $# $^

modifying a cpp make file to .c file is not working

I am trying to modify a makefile that builds cpp to a c file, but I am running into some string substitution problem. I wonder if someone can point out the mistake.
here's a piece of the file:
SOURCES := \
lz4.c \
lz4frame.c \
lz4hc.cpp \
xxhash.c
OBJECTS := $(addprefix $(OBJ_DIR)/,$(subst .c,.o,$(SOURCES)))
DEPENDS := $(addprefix $(OBJ_DIR)/,$(subst .c,.d,$(SOURCES)))
all: $(OUT_DIR)/$(LIB_NAME)
clean:
rm -rf $(OBJ_DIR)
rm -rf $(OUT_DIR)
$(OUT_DIR)/$(LIB_NAME): $(OBJECTS)
#rm -f $#
$(AR) cr $# $^
$(OBJECTS): $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
#mkdir -p $(#D)
$(CXX) -MMD -MF $(OBJ_DIR)/$*.d -MP -MT'$(OBJ_DIR)/$*.o $(OBJ_DIR)/$*.d' -c $(CPPFLAGS) $(CXXFLAGS) $< -o $#
.PHONY: all clean
-include $(DEPENDS)
but when I typed make clean I get this:
Makefile:38: target `Release64/obj/lz4hc.opp' doesn't match the target pattern
or when I try to build I get this:
g++-4.6 -MMD -MF ./Release64/obj/Release64/obj/lz4hc.opp.d -MP -MT'./Release64/obj/Release64/obj/lz4hc.opp.o ./Release64/obj/Release64/obj/lz4hc.opp.d' -c -I../../../include -I../../../thirdparty/include/lz4 -std=c++0x -fPIC -O2 -m64 -o Release64/obj/lz4hc.opp
g++-4.6: fatal error: no input files
compilation terminated.
I think the issue is with this line, but I can't figure out the problem:
OBJECTS := $(addprefix $(OBJ_DIR)/,$(subst .c,.o,$(SOURCES)))
DEPENDS := $(addprefix $(OBJ_DIR)/,$(subst .c,.d,$(SOURCES)))
thx!
Your sources variable is:
SOURCES := \
lz4.c \
lz4frame.c \
lz4hc.cpp \
xxhash.c
Note the filename lz4hc.cpp. Then you substitute .c with .o, that gives you a filename of lz4hc.opp which is exactly the error you see.
It's not clear if you really want a mix of C and C++ files, or if you just forgot to change the name of one of the files in the variable.
You can split C and C++ sources into separate lists, and use pattern rules to build your sources, e.g.:
SOURCES_C := \
lz4.c \
lz4frame.c \
xxhash.c
SOURCES_CPP:= lz4hc.cpp
SOURCES:=$(SOURCES_C) $(SOURCES_CPP)
OBJECTS_C := $(addprefix $(OBJ_DIR)/,$(subst .c,.o,$(SOURCES_C)))
OBJECTS_CPP:=$(addprefix $(OBJ_DIR)/,$(subst .cpp,.o,$(SOURCES_CPP)))
OBJECTS:=$(OBJECTS_C) $(OBJECTS_CPP)
DEPENDS_C := $(addprefix $(OBJ_DIR)/,$(subst .c,.d,$(SOURCES_C)))
DEPENDS_CPP := $(addprefix $(OBJ_DIR)/,$(subst .cpp,.d,$(SOURCES_CPP)))
DEPENTS:=$(DEPENDS_C) $(DEPENDS_CPP)
all: $(OUT_DIR)/$(LIB_NAME)
clean:
$(RM) $(OBJECTS) $(DEPENDS)
$(OUT_DIR)/$(LIB_NAME): $(OBJECTS)
#rm -f $#
$(AR) cr $# $^
%.o: %.c
#mkdir -p $(#D)
$(CC) -MMD -MF $(OBJ_DIR)/$*.d -MP -MT'$(OBJ_DIR)/$*.o $(OBJ_DIR)/$*.d' -c $(CPPFLAGS) $(CXXFLAGS) $< -o $#
%.o: %.cpp
#mkdir -p $(#D)
$(CXX) -MMD -MF $(OBJ_DIR)/$*.d -MP -MT'$(OBJ_DIR)/$*.o $(OBJ_DIR)/$*.d' -c $(CPPFLAGS) $(CXXFLAGS) $< -o $#
.PHONY: all clean
-include $(DEPENDS)
You have a file that ends in .cpp, but your subst commands only deal with names that end in .c. Try:
OBJECTS := $(addprefix $(OBJ_DIR)/,$(subst .c,.o,$(subst .cpp,.o,$(SOURCES))))
DEPENDS := $(addprefix $(OBJ_DIR)/,S(subst .c,.d,$(subst .cpp,.d,$(SOURCES))))

create objects files depending on the name of target

Is it possible to create objects files in makefile depending on the name of the target?
something like
all : gsm gsm_db
if make gsm
%.o : %.cpp
$(CC) $(CFLAGS) $< -o $#
if make gsm_db
%.o : %.cpp
$(CC) $(CFLAGS_DB) $< -o $#
Something like this should work:
ifneq "$(filter gsm_db, $(MAKECMDGOALS))" ""
%.o : %.cpp
$(CC) $(CFLAGS_DB) $< -o $#
else
%.o : %.cpp
$(CC) $(CFLAGS) $< -o $#
endif

Resources