gcc undefined reference with reference paths defined in makefile - gcc

I am learning GCC and have some undefined reference errors when running make. I am using a makefile which I did not create, however while troubleshooting these undefined reference errors I went through each line of the makefile to understand what is happening and try to fix the problem but haven't been successful although I did learn a lot about the syntax used in the makefile.
Here is the undefined reference output when using make:
/usr/bin/arm-none-eabi-gcc -O0 -g -mcpu=cortex-m3 -mthumb -I/home/np/STMBook -I/home/np/STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x -I/home/np/STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/CMSIS/CM3/CoreSupport -I/home/np/STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/STM32F10x_StdPeriph_Driver/inc -I. -DSTM32F10X_MD_VL -DUSE_STDPERIPH_DRIVER -DUSE_FULL_ASSERT -I/home/np/STMBook/Library/ff9/src -I/home/np/STMBook/Library -T/home/np/STMBook/stm32f100.ld -mthumb -mcpu=cortex-m3 BlinkLight.c -o BlinkLight
/usr/lib/gcc/arm-none-eabi/4.8.2/../../../arm-none-eabi/bin/ld: warning: cannot find entry symbol Reset_Handler; defaulting to 08000000
/tmp/ccZbJmMi.o: In function `main':
/home/np/STMBook/BlinkLight.c:11: undefined reference to `RCC_APB2PeriphClockCmd'
/home/np/STMBook/BlinkLight.c:14: undefined reference to `GPIO_StructInit'
/home/np/STMBook/BlinkLight.c:18: undefined reference to `GPIO_Init'
/home/np/STMBook/BlinkLight.c:21: undefined reference to `SystemCoreClock'
/home/np/STMBook/BlinkLight.c:21: undefined reference to `SystemCoreClock'
/home/np/STMBook/BlinkLight.c:30: undefined reference to `GPIO_WriteBit'
collect2: error: ld returned 1 exit status
make: *** [BlinkLight] Error 1
And here is my makefile which has two parts:
Part 1:
TEMPLATEROOT = /home/np/STMBook
# compilation flags for gdb
CFLAGS += -O0 -g
ASFLAGS += -g
# object files
OBJS= $(STARTUP) BlinkLight.o
OBJS+= stm32f10x_gpio.o stm32f10x_rcc.o
# include common make file
include $(TEMPLATEROOT)/Makefile.common
Part 2 (makefile.common):
# name of executable
ELF=$(notdir $(CURDIR)).elf
# Tool path
TOOLROOT=/usr/bin
# Library path
LIBROOT=/home/np/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
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)
Here is my understanding:
The undefined references are contained in files stm32f10x_gpio.c (GPIO undefined references) and stm32f10x_rcc.c (RCC undefined reference) and these are declared as required objects in the OBJS variable in Part 1 of the makefile:
OBJS= $(STARTUP) BlinkLight.o
OBJS+= stm32f10x_gpio.o stm32f10x_rcc.o
Undefined reference 'SystemCoreClock' is located in system_stm32f10x.c file in the directory given in the makefile as:
STARTUP= startup_stm32f10x.o system_stm32f10x.o
and is included in the OBJS variable.
The path to the .c files for compiling the required objects are defined in the makefile:
Location of stm32f10x_gpio.c and stm32f10x_rcc.c:
vpath %.c $(PERIPH)/src
Location of system_stm32f10x.c:
vpath %.c $(DEVICE)
All of the required objects which contain the undefined references are passed to the target build instructions as variable OBJS:
$(ELF) : $(OBJS)
$(LD) $(LDFLAGS) -o $# $(OBJS) $(LDLIBS)
Also included in the makefile is build instructions on how to obtain the object files from the C source files:
%.o: %.c
$(CC) -c $(CFLAGS) $< -o $#
$(CC) -MM $(CFLAGS) $< > $*.d
I do not understand why it seems to be that the C source files cannot be found. Thank you for any suggestions, I really appreciate any help.
Sorry for my post being so long, I tried to go through each line of the makefile and research all the symbols and syntax to figure out the problem on my own and went through many of the undefined reference questions on this site but have not figured it out.

Related

How can my makefile include subdirectories?

(updated for clarity) (solution added at bottom)
I found a makefile online which builds all the cpp files in that directory and compiles them.
But I can't work out how I can include files inside a subdirectory.
Here's a breakdown of what happens:
I create the files test.cpp & test.hpp and place them inside the sub-directory '/gui' which is contained within my working directory, they contain the function testFunction().
Without including test.hpp, I type "make" into terminal and I receive the error:
:
g++ -c -o main.o main.cpp
main.cpp: In function 'int main(int, char**)':
main.cpp:6:2: error: 'testFunction' was not declared in this scope
testFunction();
^~~~~~~~~~~~
make: *** [<builtin>: main.o] Error 1
If I include (#include "gui/test.hpp"), I then receive a different error:
:
g++ -c -o main.o main.cpp
g++ main.o -Wall -o testfile
/usr/bin/ld: main.o: in function `main':
main.cpp:(.text+0x14): undefined reference to `testFunction()'
collect2: error: ld returned 1 exit status
make: *** [makefile:34: testfile] Error 1
But if I then add "-I/gui" or (at a guess) "-I./gui" to CFLAGS, I get the exact same error message.
Here's the makefile for reference:
TARGET = testfile
LIBS =
CC = g++
CFLAGS = -g -Wall
.PHONY: default all clean
default: $(TARGET)
all: default
OBJECTS = $(patsubst %.cpp, %.o, $(wildcard *.cpp))
HEADERS = $(wildcard *.hpp)
%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) -c $< -o $#
.PRECIOUS: $(TARGET) $(OBJECTS)
$(TARGET): $(OBJECTS)
$(CC) $(OBJECTS) -Wall $(LIBS) -o $#
clean:
-rm -f *.o
-rm -f $(TARGET)
Thanks in advance!
Updated makefile since accepted answer:
(Changes were to include directories, CC replaced with CXX, and %.c replaced with %.cpp)
TARGET = testfile
DIRS =
LDLIBS =
CXX = g++
CXXFLAGS= -g -Wall
# this ensures that if there is a file called default, all or clean, it will still be compiled
.PHONY: default all clean
default: $(TARGET)
all: default
# substitute '.cpp' with '.o' in any *.cpp
OBJECTS = $(patsubst %.cpp, %.o, $(wildcard *.cpp $(addsuffix /*.cpp, $(DIRS))))
HEADERS = $(wildcard *.h)
# build the executable
%.o: %.cpp $(HEADERS)
$(CXX) $(CXXFLAGS) -c $< -o $#
# if make is interupted, dont delete any object file
.PRECIOUS: $(TARGET) $(OBJECTS)
# build the objects
$(TARGET): $(OBJECTS)
$(CXX) $(OBJECTS) -Wall $(LDLIBS) -o $#
clean:
-rm -f *.o $(addsuffix /*.o, $(DIRS))
-rm -f $(TARGET)
To understand what's happening here you have to look up the definitions of declaration versus definition in C++ (and other languages). You should definitely do that.
A declaration (typically put into a header file) is like the address of your house. If someone wants to send you a letter, they need your address. If your main function wants to call another function like testFunction(), it needs the declaration of the function.
The first error happens because you don't have the header file included, so the compiler doesn't have the declaration of the function you want to call, which means it won't compile your calling function.
But for the letter to actually arrive, you need your actual house. The address is the declaration and your house is the definition... in this case the actual function implementation. That lives in test.cpp file. When you link your code together, the linker (in this scenario I guess the linker is like the postal service :p :) ) will try to link up the call to the definition.
However, you can see that you are not compiling the test.cpp file nor are you linking the object file:
g++ main.o -Wall -o testfile
here we see main.o, but not gui/test.o.
Why not? This line:
OBJECTS = $(patsubst %.cpp, %.o, $(wildcard *.cpp))
Matches all *.cpp files and converts them into .o files. But *.cpp matches only files in the current directory, like main.cpp. If you want to put files in a different directory you have to tell make where they are; for example:
OBJECTS = $(patsubst %.cpp, %.o, $(wildcard *.cpp gui/*.cpp))

No rule to make target *, needed by *

I can't get what's wrong with my makefile:
DIST_PATH = ../dist/libs
BUILD_PATH = ../build
MKDIR_P = mkdir -p
.PHONY: all
SHELL = /bin/sh
CC = gcc
FLAGS = -std=gnu99
CFLAGS = -fPIC -pedantic -Wall -Werror
LDFLAGS = -shared
LOG_SRCS = $(shell echo log/*.c)
LOG_HEADERS = $(shell echo log/*.h)
LOG_OBJS = $(addprefix $(BUILD_PATH)/, $(notdir $(LOG_SRCS:.c=.o)))
LOG_TARGET = $(DIST_PATH)/liblog.so
all: dirs $(LOG_TARGET)
dirs :
$(MKDIR_P) $(DIST_PATH)
$(MKDIR_P) $(BUILD_PATH)
$(LOG_TARGET) : $(LOG_OBJS)
$(CC) $(FLAGS) $(CFLAGS) -o $# $(LDFLAGS)
I need to build a shared library from sources in log/ folder to ../dist/libs and put obj file in ../build but I am getting the error:
make: *** No rule to make target '../build/log.o', needed by '../dist/libs/liblog.so'. Stop.
P.S. I know there are many similar questions but I couldn't get from these questions how to resolve my problem.
The problem is that the source and object files are supposed to be placed in different directories, and there's no implicit rule for that.
You need to add a rule for how to translate a source file to an object file:
$(BUILD_PATH)/%.o: log/%.c
Now make knows how to create the object files from the source files.
There's another problem though:
$(LOG_TARGET) : $(LOG_OBJS)
$(CC) $(FLAGS) $(CFLAGS) -o $# $(LDFLAGS)
The command doesn't list any input files, you need to add all the object files to be linked:
$(LOG_TARGET) : $(LOG_OBJS)
$(CC) $(FLAGS) $(CFLAGS) -o $# $^ $(LDFLAGS)
# ^^
# List of all "prerequisites" (object files) to be linked

Error on makefile with threads and my library

So I have been searching and looking for something that could help me with the Makefile, but I did not find anything, so thats why I am here.
My makefile right now is like this:
CC = gcc
CFLAGS = -Wall
LDFLAGS += -L$(LIBB)
LDFLAGS += -static lib1.h
LDLIBS = -lm -lpthread -lrt -l
SOURCES=lib1.c prac3.c prac3_reader.c
LIBRARIES=lib1.o
INCLUDES=lib1.h
PROGRAMS=prac3 prac3_reader
all: $(OBJS) $(PROGRAMS)
$(PROGRAMS): $(LIBRARIES) $(INCLUDES)
$(CC) $(LDFLAGS) $(LIBRARIES) $(LDLIBS) $#.o -o $#
%.o: %.c $(INCLUDES)
$(CC) $(CFLAGS) -o $# -c $<
clean:
rm -rf *.o *~ $(PROGRAMS)
I know there are probably a lot of things that can be removed, but I do not really know which ones are. I have two programs called
prac3.c
and
prac3_reader.c
Also, I have my own library called
lib1.c
and also compiled like
lib1.h
When I go to my directory with the terminal and use the command make I recive this error:
gcc -L -static lib1.h lib1.o -lm -lpthread -lrt -l prac3.o -o prac3
/usr/bin/ld: no se puede encontrar -lprac3.o
collect2: error: ld returned 1 exit status
Makefile:15: recipe for target 'prac3' failed
make: *** [prac3] Error 1
I am running on Ubuntu.
The -l flag expects an argument. When it is combined in the gcc statement it causes the prac3.o argument to be considered as the name of a library. There is no such library prac3.o, so you get the error.
In general .o files aren't "libraries". They are object files. Remove the -l flag and you will be fine.
"libraries" are generally .a or .so files from a library path - but even then, you wouldn't specify the suffix (.e.g "-lpthreads").

Makefile add last flag

I am trying to compile my project using makefile.
Command line that works perfectly for me is:
g++ -I stuff/ -L stuff2/ src/Core.cpp -o file_name -ljvm
If I miss -ljvm at the end I end up with an error while compiling, this flag must go after file_name. The problem is that I am unable to add -ljvm successfully using makefile.
My makefile looks like this:
NAME = 'AI'
SRC = src
TGT = obj
PRG = application
INCLUDES = -Iinclude -I /usr/lib/jvm/java-7-openjdk-amd64/include/
LIBRARIES = -L /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/amd64/server/
CXXFLAGS = -Wall -O3 -std=c++0x $(INCLUDES) $(LIBRARIES)
SOURCES = $(wildcard $(SRC)/*.cpp)
OBJS = $(addprefix $(TGT)/, $(notdir $(SOURCES:.cpp=.o)))
$(TGT)/%.o: $(SRC)/%.cpp
$(CXX) $(CXXFLAGS) -c $< -o $#
$(PRG)/$(NAME): $(OBJS)
$(CXX) $(LDFLAGS) $(OBJS) -o $#
Which gives me an error since I have not added -ljvm.
If I add it to: $(CXX) $(CXXFLAGS) -c $< -o $# -ljvm, nothing changes and I still get same error.
If I add it to last line $(CXX) $(LDFLAGS) $(OBJS) -o $# -ljvm I get a different error:
g++ obj/Core.o -o application/'AI' -ljvm
/usr/bin/ld: cannot find -ljvm
collect2: error: ld returned 1 exit status
make: *** [application/'AI'] Error 1
I have a feeling that I am missing something simple here. Any suggestions are much appreciated.
Your last line uses $(LDFLAGS) that is actually never defined.
ld complains about the fact it cannot find -ljvm, that's because you have to pass
-L /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/amd64/server/
to the linker (i.e. add it to your last command).
Try defining LDFLAGS with, at least, $(LIBRARIES) in it.

Creating a FORTRAN makefile

I have a FORTRAN source code consisting of many different .F and .h files. I need to build an executable from it, but I'm having some problems. The makefile that I produced so far (which may have errors as I'm new to this) is:
# compiler
FC = /usr/bin/gfortran-4.5
# compile flags
FCFLAGS = -g -c -fdefault-real-8 -fbacktrace -fno-align-commons
# link flags
FLFLAGS = -g -fbacktrace
# source files and objects
SRCS = $(patsubst %.F, %.o, $(wildcard *.F)) \
$(patsubst %.h, %.mod, $(wildcard *.h))
# program name
PROGRAM = blah
all: $(PROGRAM)
$(PROGRAM): $(SRCS)
$(FC) $(FCFLAGS) $# $<
%.o: %.F
$(FC) $(FLFLAGS) -o $# $<
%.mod: %.h
$(FC) $(FLFLAGS) -o $# $<
clean:
rm -f *.o *.mod
When I try to make the program, however, I'm getting a slew of undefined reference errors. I mean, every function and subroutine call in the very first compiled .F file gives back an undefined reference error. I thought this was because gfortran was trying to link the files instead of just compiling them and then linking at the end, but I thought the '-c' option was supposed to prevent that.
UPDATE:
As commenters have pointed out, I mixed up the compile and link flags. Furthermore, you shouldn't compile *.h files. Here is the latest, corrected makefile:
# compiler
FC = /usr/bin/gfortran-4.4
# compile flags
FCFLAGS = -g -c -fdefault-real-8 -fbacktrace -fno-align-commons -fbounds-check -std=legacy
# link flags
FLFLAGS =
# source files and objects
SRCS = $(patsubst %.F, %.o, $(wildcard *.F))
# program name
PROGRAM = blah
all: $(PROGRAM)
$(PROGRAM): $(SRCS)
$(FC) $(FLFLAGS) -o $# $<
%.o: %.F
$(FC) $(FCFLAGS) -o $# $<
clean:
rm -f *.o *.mod
Now when I run make, it will compile each *.F file in the code, but it fails at the linking stage. I get a bunch of undefined reference errors in the very first *.F file. The compiler seems to be going over each *.F file individually in the linking stage, which I'm not sure is correct. Then I get an error:
/usr/lib/gcc/x86_64-linux-gnu/4.4.5/libgfortranbegin.a(fmain.o): In function `main':
(.text+0x26): undefined reference to `MAIN__'
collect2: ld returned 1 exit status
However, if I type the command:
gfortran -o blah *.o
The executable will be built, so it seems like I did something wrong in the makefile for the linking stage.
UPDATE: 5/9/2011
Sverre pointed out the final problem with my makefile. In my first target that builds the program, I use the shortcut command for only the first dependency ($<), but I need to include all dependencies (i.e. all *.o files) using the ($^) shortcut. The final, working makefile is as follows:
# compiler
FC := /usr/bin/gfortran-4.5
# compile flags
FCFLAGS = -g -c -fdefault-real-8 -fbacktrace -fno-align-commons -fbounds-check
# link flags
FLFLAGS =
# source files and objects
SRCS = $(patsubst %.F, %.o, $(wildcard *.F))
# $(patsubst %.h, %.mod, $(wildcard *.h))
# program name
PROGRAM = vipre
all: $(PROGRAM)
$(PROGRAM): $(SRCS)
$(FC) $(FLFLAGS) -o $# $^
%.o: %.F
$(FC) $(FCFLAGS) -o $# $<
# %.mod: %.h
# $(FC) $(FCFLAGS) -o $# $<
clean:
rm -f *.o *.mod
Are you using GNU make? If so,
$(FC) $(FLFLAGS) -o $# $<
may be the culprit. $< is the name of the first prerequisite, but you want all the *.o files. Try using $^ instead.

Resources