I'm trying to compile someone else's fortran code and getting undefined reference errors. In particular, I get errors like this:
/usr/lib64/cernlib/2006/lib/libpdflib804.a(structm.o): In function `structm_':
(.text+0x17712): undefined reference to `_gfortran_transfer_integer'
My guess is that I'm not properly linking libpdflib804.a, but I do not know what I am doing wrong. Here is the makefile:
OBJS = hpair.o Cteq61Pdf.o mrst2001.o
LIBS = $(CERN)/libpdflib804.a $(CERN)/libpawlib.a $(CERN)/libgrafX11.a $(CERN)/libpacklib.a $(CERN)/libmathlib.a $(CERN)/libkernlib.a
FC=f77
.f.o:
$(FC) -c $(FFLAGS) $*.f
hpair: $(OBJS)
$(FC) $(FFLAGS) $(OBJS) $(LIBS) -o run
clean:
rm -f $(OBJS)
My system has various those libraries in various locations (it is the cluster at CERN), but all the possible different options for $CERN give me similar errors.
Try adding -lgfortran or the explicit path to libgfortran.a. The undefined symbol should be there. Is f77 some other compiler? That would explain it.
Related
I'm writing a small study project in C. I need to create a dynamic library and configure its use with macros. First, I create object files with the command:
$gcc -fPIC -c ../data_module/data_process.c
$gcc -fPIC -c ../data_libs/data_stat.c
Then I create a dynamic library like this:
$gcc -shared -o data_process.so data_process.o data_stat.o
And finally I build an executable file using this library:
$gcc main_executable_module.o ../data_libs/data_io.o ../yet_another_decision_module/decision.o -L. data_process.so -o test_main
It works and the executable works correctly. But there is a task to configure the library using macros:
Make the necessary changes to the code of the main_executable_module, configuring the use of the dynamic library using macros.
That is, if I understand correctly, you need to add macros to the main_executable_module.o so that you do not use the -L flags during assembly. But I can't find information anywhere on how to do it. Can you please tell me how to implement this or where can I read about it?
UPD: John Bollinger says
It is possible that the word "macros" is intended to be interpreted as makefile macros, which many people instead call (makefile) "variables". That would make this a question about make / makefiles, not about C.
My Makefile:
CC=gcc
LDFLAGS=
CFLAGS=-c -Wall -Wextra -Werror
SOURCES=main_executable_module.c ../data_libs/data_stat.c ../data_libs/data_io.c ../yet_another_decision_module/decision.c ../data_module/data_process.c
DYNLIB=../data_module/data_process.c
STAT=../data_libs/data_stat.c
BUILDDYN=main_executable_module.c ../data_libs/data_io.c ../yet_another_decision_module/decision.c
OBJECTS=$(SOURCES:.c=.o)
OBJBUILDDYN=$(BUILDDYN:.c=.o)
OBJDYNLIB=data_process.o
OBJDATASTAT=data_stat.o
EXECUTABLE=../../build/main
DEXECUTABLE=../../build/Quest_6
DLIBS=data_process.so
all: $(SOURCES) $(EXECUTABLE)
data_stat.a: $(OBJLIB) $(LIBS)
ar -rcs $(LIBS) $(OBJLIB)
data_process.so: $(OBJDYNLIB) $(OBJDATASTAT)
$(CC) -shared -o $(DLIBS) $(OBJDYNLIB) $(OBJDATASTAT)
$(OBJDYNLIB): $(DYNLIB)
$(CC) -fPIC -c $(DYNLIB)
$(OBJDATASTAT): $(STAT)
$(CC) -fPIC -c $(STAT)
build_with_dynamic:$(OBJECTS) $(EXECUTABLE)
$(CC) $(OBJBUILDDYN) -L. $(DLIBS) -o $(DEXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.c.o:
$(CC) $(CFLAGS) $< -o $#
clean:
rm -rf $(EXECUTABLE) $(OBJECTS)
lclean:
rm -rf $(LEXECUTABLE) $(OBJECTS) $(LIBS) $(DEXECUTABLE)
rebuild: clean $(SOURCES) $(EXECUTABLE)
The results of the checks revealed nothing. There are two opinions about this task.
Leave everything as above. And in the file itself, add a header process.h. Then everything is assembled and working. And at the same time, if you change the code in the library, rebuild it, and do not rebuild the executable file, then the changes will be taken into account. That is, the idea of a dynamic library is respected.
Implement in such a way that there is no need to include headers in the main_executable_module.c. Then a special library is used for working with dynamic libraries, which allows you to write the path to the library and take individual functions from it. More about it here.
What was meant when it was said about macros, I still did not understand ...
I have program (in fortran) where I'm using three custom modules, which make use of LAPACK. Until now I've compiled my program using the following shell script:
filestring="main"
gfortran -c mod_exp.f90 mod_genmat.f90 mod_print.f90 $filestring.f90
gfortran mod_exp.o mod_genmat.o mod_print.o $filestring.o -llapack -lblas
rm mod_exp.o mod_genmat.o mod_print.o $filestring.o exponentiate.mod genmat.mod printing.mod printing_subrtns.mod
mv a.out $filestring
Since I've been using more and more modules and different programs using them, I've decided to start using makefiles. Following a tutorial, I managed to write the following:
FC = gfortran
FFLAGS = -Wall -Wextra -llapack -lblas #-fopenmp
SOURCES = mod_print.f90 mod_genmat.f90 mod_exp.f90 main.f90
OBJ = ${SOURCES:.f90=.o} #substitute .f90 with .o
%.o : %.f90 #creation of all *.o files DEPENDS on *.f90
$(FC) $(FFLAGS) -c -O $< -o $#
main: $(OBJ)
$(FC) $(FFLAGS) -o $# $(OBJ)
clean:
#rm -f *.o *.mod main
However, when executing make, it says that the LAPACK functions are not recognized. One such mistake is the following:
/usr/bin/ld: mod_exp.o: in function `__exponentiate_MOD_diagun':
mod_exp.f90:(.text+0x37f): undefined reference to `zgees_'
...
collect2: error: ld returned 1 exit status
One possible mistake I've seen is that I need to specify the location of the libraries. However, it would seem strange since I didn't need to do it before; also, I don't know how to find it.
Please show the link command that make invoked, that caused the error to be generated.
I'm confident that if you cut and paste that exact command line to your shell prompt, you will get the same error you see when make runs it. So the problem is not make, but your link command.
The problem is that you have put the libraries before the objects in the link line. Libraries should come at the end, after the objects, else when the linker examines the libraries it doesn't know what symbols will need to be included (because no objects have been parsed yet to see what symbols are missing).
This is why LDLIBS is traditionally a separate variable:
FC = gfortran
FFLAGS = -Wall -Wextra #-fopenmp
LDLIBS = -llapack -lblas
SOURCES = mod_print.f90 mod_genmat.f90 mod_exp.f90 main.f90
OBJ = ${SOURCES:.f90=.o} #substitute .f90 with .o
%.o : %.f90 #creation of all *.o files DEPENDS on *.f90
$(FC) $(FFLAGS) -c -O $< -o $#
main: $(OBJ)
$(FC) $(FFLAGS) -o $# $(OBJ) $(LDLIBS)
I am trying to build a project with make (gcc on Raspbian)
Here is the makefile (I removed some unnecessary parts):
objects = 3d.o Affichage.o [...]
cflags = -I/usr/local/include/SDL2 -L/usr/local/lib -lSDL2
poly : %(objects)
gcc $(cflags) $(objects) -o poly
($objects) : types.h
[...]
When running Make, I got:
cc -c -o Affichage.o Affichage.c
fatal error: SDL.h: No such file or directory
#include <SDL.h>
I checked the folders, everything seems ok. SDL.h is indeed in /usr/local/include/SDL2. I tried to remove options one by one in cflags, no luck...
What am I missing?
Make told you exact command it tried to execute:
cc -c -o Affichage.o Affichage.c
This don't have -I path, which is the source of an error.
You have target for your resulting executable but not for object files. Make have builtin rule to compile object files from C sources, but it isn't aware of your cflags variable. So far your options are:
Define your own pattern rule
e.g:
%.o: %.c
gcc $(cflags) -c $< -o $#
However, your cflags contains -lSDL2, which is linking flag, which should be specified only on linking phase (so technically it isn't cflag). Move it to separate variable (usually LIBS, which may then be enfolded into make's semi-standard LDFLAGS).
Use variables that make is aware of
In that case, it is CFLAGS:
CC:=gcc
CFLAGS:=-I/usr/local/include/SDL2
LIBS:=-lSDL2
LDFLAGS:=-L/usr/local/lib $(LIBS)
objects:=3d.o Affichage.o
poly: $(objects)
$(CC) $^ -o $# $(LDFLAGS)
$(objects): types.h
The rest will be done by implicit rules.
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.
I want to make static XGBoost library, but I'm failing at this easy task.
Firstly, I simply tried to take all .o files and via ar rcs wrapper/libxgboostwrapper.a ./* make static library, but I failed. In fact, when I'm making other stuff which depends on XGBoost it fails with errors: undefined reference to XGBoosterFree.
This function is defined in wrapper part and there is no file wrapper/libxgboostwrapper.o. So in order to make a static library firstly we have to create wrapper/libxgboostwrapper.o, secondly, run ar rcs on all needed .o files.
How I modified Makefile.
Firstly, I slightly changed names of some variables.
ifeq ($(OS), Windows_NT)
LIBRABIT = subtree/rabit/lib/librabit_empty.a
DLIB = wrapper/xgboost_wrapper.dll
SLIB = wrapper/xgboost_wrapper.lib
else
LIBRABIT = subtree/rabit/lib/librabit.a
DLIB = wrapper/libxgboostwrapper.so
SLIB = wrapper/libxgboostwrapper.a
endif
Added new variable.
WRAP = wrapper/libxgboostwrapper.o
Modified target.
TARGET = $(BIN) $(OBJ) $(DLIB) $(SLIB) $(WRAP)
Added dependencies for wrapper/libxgboostwrapper.o exactly the same as for wrapper/libxgboostwrapper.so.
wrapper/libxgboostwrapper.o: wrapper/xgboost_wrapper.cpp src/utils/*.h src/*.h src/learner/*.hpp src/learner/*.h updater.o gbm.o io.o $(LIBRABIT) $(LIBDMLC)
After everything is done for $(BIN), $(MOCKBIN), $(DLIB), I'm trying to compile (or make?) my $(WRAP).
$(WRAP) :
$(CXX) $(CFLAGS) -fPIC -o $# $(filter %.cpp %.o %.c %.a %.cc, $^) $(LDFLAGS) $(DLLFLAGS)
After all this stuff finally I'm making wrapper/libxgboostwrapper.a.
$(SLIB) : updater.o gbm.o io.o $(WRAP) $(LIBRABIT) $(LIBDMLC)
ar rcs $# $^
It fails at step 5 with errors like:
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 0 has invalid symbol index 10
What am I doing wrong? For me it seems like compilation .so and .o files shuld be the same except flag -shared is not used.
This may take a few iterations, since you seem to have a few misconceptions about how these files work.
STEP 1: First, let's compile a source file to produce an object file:
g++ -o wrapper/xgboostwrapper.o -c wrapper/xgboost_wrapper.cpp
(Don't call the object file "libxgboostwrapper.o". The "lib" prefix is for a library, the ".o" suffix is for an object file, when you use them both it's just confusing.)
Do not proceed until that works.
STEP 2: Write a rule in your makefile to do it:
wrapper/xgboostwrapper.o: wrapper/xgboost_wrapper.cpp
$(CXX) $(CFLAGS) -o $# $<
Do not proceed until that works.
STEP 3: Figure out which header files it actually needs, and add those as prerequisites. (It's a bad idea to use wildcards to add all existing headers as prerequisites.):
wrapper/xgboostwrapper.o: wrapper/xgboost_wrapper.cpp src/utils/foo.h src/xgboost.h
$(CXX) $(CFLAGS) -o $# $<
Try that much and tell us how it went, then we can proceed.