I'm trying to use powf function in an rtems application.
When I call powf(a,b); inside Init() function, it compiles ok.
But when I call powf in some other function, the compiler gives me 'undefined reference to powf' message even though I have those #include <math.h> and #include <float.h>. I event tried merging the file, but it is the same.
#define CONFIGURE_...
#define CONFIGURE_...
#include <rtems/confdefs.h>
rtems_task Init( rtems_task_argument ignored)
{
powf(a,b); // ok
}
int my_other_func()
{
powf(c,d); // undefined reference error..
}
What can be the problem?
EDIT(ADD) : I added source code and makefile below. The compiled rtems OS package is specified by shell environment variable RTEMS_MAKEFILE_PATH.
Makefile :
include ../Makefile.base
_RAM_START = 0x60000000
XCFLAGS = -qnolinkcmds -T ../../lib/linkcmds.abts3 -D_RAM_START=$(_RAM_START)
XCFLAGS += -lm -DALDEBARAN_RTEMS
../Makefile.base :
#
# RTEMS_MAKEFILE_PATH is typically set in an environment variable
#
PGM=${ARCH}/faster_rcnn.exe
# optional managers required
MANAGERS=all
# C source names
VPATH = ../src
VPATH += ../../../../abfrcnn/bare-c/lrn_layer
CSRCS = init.c
CSRCS += lrn_layer.c
CSRCS1 = $(notdir $(CSRCS))
COBJS_ = $(CSRCS1:.c=.o)
include $(RTEMS_MAKEFILE_PATH)/Makefile.inc
include $(RTEMS_CUSTOM)
include $(PROJECT_ROOT)/make/leaf.cfg
#XCFLAGS += -I../../include
COBJS = $(COBJS_:%=${ARCH}/%)
OBJS= $(COBJS) $(CXXOBJS) $(ASOBJS)
#all: ${ARCH} $(PGM) RUNTCL
all: ${ARCH} $(PGM)
$(PGM): $(OBJS)
$(make-exe)
RUNTCL:
echo 'system_init' > run.tcl
echo 'load_image o-optimize/faster_rcnn.exe' >> run.tcl
echo 'run $(_RAM_START)' >> run.tcl
clean:
-$(RM) -r $(ARCH)
../src/init.c :
...
#include <math.h>
rtems_status Init(rtems_argument ignored)
{
...
printf(" pow(1.1,2.2) = %f\n", powf(1.1,2.2)); // <== powf compiles liks ok
//zf_coco();
}
../../../../abfrcnn/bare-c/lrn_layer/lrn_layer.c
#include <stdio.h>
#include <math.h>
int lrn_layer(... args... )
{
...
val = 1./powf((1.+a/(float)(k^2)*tmp),b); // method1
...
} // main ROI loop
The result of make command :
test -d o-optimize || mkdir o-optimize
sparc-ab-rtems-gcc --pipe -B/home/ckim/prj/abts/rtems-qt/rtems-4.10.99-kernel/build-rtems/rtems-package/sparc-ab-rtems/aldebaran2/lib/ -specs bsp_specs -qrtems -Wall -qnolinkcmds -T ../../lib/linkcmds.abts3 -D_RAM_START=0x60000000 -lm -DALDEBARAN_RTEMS -O4 -mtune=v8 -msoft-float -fcommon -DTARGET_ALDEBARAN -c -o o-optimize/init.o ../src/init.c
../src/init.c:120:2: warning: missing braces around initializer [-Wmissing-braces]
{0}, // rtems_chain_control;
^
../src/init.c:120:2: warning: (near initialization for 'ald_sd_card_driver_table[0].queue.Chain') [-Wmissing-braces]
sparc-ab-rtems-gcc --pipe -B/home/ckim/prj/abts/rtems-qt/rtems-4.10.99-kernel/build-rtems/rtems-package/sparc-ab-rtems/aldebaran2/lib/ -specs bsp_specs -qrtems -Wall -qnolinkcmds -T ../../lib/linkcmds.abts3 -D_RAM_START=0x60000000 -lm -DALDEBARAN_RTEMS -O4 -mtune=v8 -msoft-float -fcommon -DTARGET_ALDEBARAN -c -o o-optimize/lrn_layer.o ../../../../abfrcnn/bare-c/lrn_layer/lrn_layer.c
../../../../abfrcnn/bare-c/lrn_layer/lrn_layer.c: In function 'lrn_layer':
../../../../abfrcnn/bare-c/lrn_layer/lrn_layer.c:201:12: warning: 'w_idx' may be used uninitialized in this function [-Wmaybe-uninitialized]
if (w_idx == w && h_idx == h) {
^
sparc-ab-rtems-gcc --pipe -B/home/ckim/prj/abts/rtems-qt/rtems-4.10.99-kernel/build-rtems/rtems-package/sparc-ab-rtems/aldebaran2/lib/ -specs bsp_specs -qrtems -Wall -qnolinkcmds -T ../../lib/linkcmds.abts3 -D_RAM_START=0x60000000 -lm -DALDEBARAN_RTEMS -O4 -mtune=v8 -msoft-float -fcommon -DTARGET_ALDEBARAN -L/opt/abde-rtems/lib/gcc/sparc-ab-rtems/4.8.2/soft -L/opt/abde-rtems/sparc-ab-rtems/lib/soft -mtune=v8 -msoft-float -fcommon -DTARGET_ALDEBARAN -o o-optimize/faster_rcnn.exe o-optimize/init.o o-optimize/lrn_layer.o
o-optimize/lrn_layer.o: In function `lrn_layer':
lrn_layer.c:(.text+0x4a8): undefined reference to `powf'
collect2: error: ld returned 1 exit status
make: *** [o-optimize/faster_rcnn.exe] Error 1
The compile process is composed of compilation of each individual .c files and final linking. I found somehow the -lm option which was added through XCFLAGS is being applied to the compilation command but not in the linking command. So I added -lm option in the object list so that that option is naturally following the object list in the link command. (I guess the proper way is to add -lm to the XLDFLAG because I found the variable in rtems build tree : extra LD flags). I'll try later..
OBJS= $(COBJS) $(CXXOBJS) $(ASOBJS) -lm
Related
I am trying to compile a minimal test shared library in FreeBSD using:
FreeBSD clang version 6.0.1 (tags/RELEASE_601/final 335540) (based on LLVM 6.0.1)
Target: x86_64-unknown-freebsd12.0
Thread model: posix
InstalledDir: /usr/bin
test.c
#include "test.h"
int SampleFunction(int a, int b)
{
return a * b;
}
test.h
#ifndef TESTLIB_H
#define TESTLIB_H
extern int SampleFunction(int a, int b);
#endif
Makefile
# Makefile TESTLIB
TEST_OBJS = test.o
TEST_HEADERS = test.h
TEST_LIB = test.so
CC = cc
testlib: $(TEST_OBJS)
$(CC) -fpic -o $(TEST_LIB) $(TEST_OBJS)
# Rebuilt if this Makefile or header changes
$(TEST_OBJS): Makefile $(TEST_HEADERS)
Output:
$ make testlib
cc -O2 -pipe -c test.c -o test.o
cc -fpic -o test.so test.o
/usr/bin/ld: error: undefined symbol: main
>>> referenced by crt1.c:76 (/usr/src/lib/csu/amd64/crt1.c:76)
>>> /usr/lib/crt1.o:(_start)
cc: error: linker command failed with exit code 1 (use -v to see invocation)
*** Error code 1
Stop.
make: stopped in /usr/home/user/testlib
As well as adding -shared to the linker stage (as mentioned by Oo.oO), you probably also want to compile with the -fPIC flag as well. So if you are using the makefile implicit rules for the compiling (looks like you are) then you will probably want to add that flag to CFLAGS. I don't think you need it for the linking stage:
# Makefile TESTLIB
TEST_OBJS = test.o
TEST_HEADERS = test.h
TEST_LIB = test.so
CFLAGS += -fPIC
CC = cc
testlib: $(TEST_OBJS)
$(CC) -shared -o $(TEST_LIB) $(TEST_OBJS)
# Rebuilt if this Makefile or header changes
$(TEST_OBJS): Makefile $(TEST_HEADERS)
I prefer using the OS-provided bsd.lib.mk for such building libraries. The following should do the right thing -- whatever it may be:
SHLIB_NAME= testlib
SRCS= test.c
.include <bsd.lib.mk>
(For building executables there is bsd.prog.mk, BTW.)
I am confused about how to inline functions in c (C99 onwards). In section 18.6 of "C programming, a modern approach" (K.N. King, 2nd edition), or for example 3 in this tutorial (under "Strategies for using inline functions"), the definition of an inline function is given in the header (.h) file, then the function is again listed as extern in a source (.c) file.
For example, what I am doing: in a header "stencil.h"
#ifindef _STENCIL_H
#define _STENCIL_H
inline double D1_center_2ndOrder(double vp1, double vm1, double dr)
{
return (vp1-vm1) / (2.0 * dr) ;
}
#endif
Then in a matching source file "stencil.c" one defines
#include "stencil.h"
extern double D1_center_2ndOrder(double vp1, double vm1, double dr) ;
I did this, and then in a file "main.c" I called average:
#include <stdio.h>
#include <stdlib.h>
#include "stencil.h"
int main(int argc, char *argv[])
{
double vp1 = 1 ;
double vp2 = 2 ;
dr = 0.1 ;
double der_v = D1_center_2ndOrder(vp1, vm1, dr) ;
printf("der_v\t%f\n", der_v) ;
return 0 ;
}
I compile everything with the following makefile
CC = gcc
CFLAGS = -Wall -lm -std=gnu11
OBJECTS = main.o stencil.o
DEPS_MAIN = stencil.h
test: $(OBJECTS)
$(CC) -o collapse $(OBJECTS) $(CFLAGS)
main.o: main.c $(DEPS_MAIN)
$(CC) -c main.c
stencil.o: stencil.c stencil.h
$(CC) -c stencil.c
And I then get the following compiler error:
gcc -c main.c
gcc -c stencil.c
gcc -o test main.o stencil.o -Wall -lm -std=gnu11
stencil.o: In function `D1_center_2ndOrder':
stencil.c:(.text+0x0): multiple definition of `D1_center_2ndOrder'
main.o:main.c:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
make: *** [collapse] Error 1
When I define the function in the .c source file "stencil.c" and declare it in the header file I do not get the above error. The version of gcc I am using is
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28).
My questions are:
(1) Why then does "C programming, a modern approach" and the tutorials on inlining functions that I find online suggest defining the function in the header file and listing it again as extern in a source file? Doing so for the above gives me a compiler error.
(2) When I declare the inline function in a header file then define as extern in a source file, will the compiler still inline my function?
You are using a portable strategy based on standard C99 (and more recent), which is entirely correct.
It is failing because you invoke gcc with its default -std setting, which for GCC 4.8.5 effectively tells it to use its legacy semantics and not standard C11 semantics. The default value for -std was gnu90 in version 4.8.5. In version 5, it was changed to gnu11, which implements C99/C11 inline semantics.
You're using default settings because your Makefile does not include $(CFLAGS) in the compile recipes; only in the final link recipe. (You can see that in the commands printed out by make).
While -std=gnu11 should work, it would be better to use -std=c11 instead. And consider upgrading to a more recent GCC version.
You need to pass the standard-version flag while compiling. It's not doing any good when you pass it in the linking stage.
So your makefile should be something like:
CC = gcc
CFLAGS = -Wall -std=gnu11
LDFLAGS = -lm
OBJECTS = main.o stencil.o
DEPS_MAIN = stencil.h
test: $(OBJECTS)
$(CC) -o collapse $(OBJECTS) $(LDFLAGS)
main.o: main.c $(DEPS_MAIN)
$(CC) -c main.c $(CFLAGS)
stencil.o: stencil.c stencil.h
$(CC) -c stencil.c $(CFLAGS)
I've tested your example with this shellscript:
#!/bin/sh -eu
cat > stencil.h <<EOF
#ifndef _STENCIL_H
#define _STENCIL_H
inline double D1_center_2ndOrder(double vp1, double vm1, double dr)
{
return (vp1-vm1) / (2.0 * dr) ;
}
#endif
EOF
cat > stencil.c <<EOF
#include "stencil.h"
extern double D1_center_2ndOrder(double vp1, double vm1, double dr) ;
EOF
cat > main.c <<EOF
#include <stdio.h>
#include <stdlib.h>
#include "stencil.h"
int main(int argc, char *argv[])
{
double vp1 = 1 ;
double vp2 = 2 ;
double dr = 0.1 ;
double vm1 = 0;
double der_v = D1_center_2ndOrder(vp1, vm1, dr) ;
printf("der_v\t%f\n", der_v) ;
return 0 ;
}
EOF
: ${CC:=gcc}
set -x
gcc -c main.c -std=c99
gcc -c stencil.c -std=c99
gcc -o test main.o stencil.o -lm
and gcc 4.6.4 and it's working fine, as long as the compilations (rather than the linking command) get at least -std=c99 (It's not working with 4.6.4's defaults).
(Side note: the header guard shouldn't start with an underscore and an uppper-case letter.)
I have to do a makefile to compile something, but I got a problem : when I type the make command, I got an error message saying that there is no rules for one of the targets. The problem is about the path to the target, using an environment var.
Here is the given start of the Makefile :
CC = mipsel-unknown-elf-gcc
AS = mipsel-unknown-elf-as
LD = mipsel-unknown-elf-ld
DU = mipsel-unknown-elf-objdump
SYS_OBJS = reset.o \
giet.o \
common.o \
ctx_handler.o \
drivers.o \
exc_handler.o \
irq_handler.o \
sys_handler.o
APP_OBJS = stdio.o main.o
GIET ?= /(my path)/giet
SYS_PATH = $(GIET)/sys
APP_PATH = $(GIET)/app
SYS_CFLAGS = -Wall -ffreestanding -mno-gpopt -mips32 -I$(SYS_PATH) -I.
APP_CFLAGS = -Wall -ffreestanding -mno-gpopt -mips32 -I$(APP_PATH) -I.
all: sys.bin app.bin
(I am supposed to finish it)
What I tried to do (rule for sys.bin works fine) :
common.o: common.c
mipsel-unknown-elf-gcc $(SYS_CFLAGS) common.o $(SYS_PATH)/common.c
The command I'm using to compile myself is : mipsel-unknown-elf-gcc -ffreestanding -mno-gpopt -mips32 -I$GIET/sys -I. -c -o common.o $GIET/sys/common.c
Could you help me to fix this ?
Thanks :)
I don't see a -o (output file specifier) at the end of $(SYS_CFLAGS) or before the common.o in the command for your rule. That's the important difference between your makefile and your manual command.
Without that specifier, it will try to act on common.o rather than produce it, attempting to combine both common.o and $(SYS_PATH)/common.c into (most likely) a.out.
To fix it, change the rule to:
common.o: common.c
mipsel-unknown-elf-gcc $(SYS_CFLAGS) -o common.o $(SYS_PATH)/common.c
# ^^
# Add this bit here (but not these two comment lines).
I try to write a makefile to create an executable .mexa64 file. I have to use the gcc compiler. My current working folder looks like this:
FFTW_build.c
FFTW_func.c
Makefile.c
obj (Folder, here are my object files *.o which are created)
Source code FFTW_build.c:
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
FFTW_perform();
return;
}
Source code FFTW_func.c:
#include <math.h>
#include <stdio.h>
#include <complex.h>
#include <fftw3.h>
#include "mex.h"
void FFTW_perform() {
int i;
int Npoints=10;
fftw_complex *in, *out;
fftw_plan plan;
in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*Npoints);
out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*Npoints);
plan = fftw_plan_dft_1d(Npoints, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
mexPrintf("\nCoefficcients of the expansion:\n\n");
for(i = 0; i < Npoints; i++)
{
in[i] = (i+1)+(3*i-1)*I;
mexPrintf("%d %11.7f %11.7f\n", i, creal(in[i]), cimag(in[i]));
}
mexPrintf("\n");
fftw_execute(plan);
mexPrintf("Output:\n\n");
for(i = 0; i < Npoints; i++)
{
mexPrintf("%d %11.7f %11.7f\n", i, creal(out[i]), cimag(out[i]));
}
}
Source code for Makefile.c:
################## Compiler ##################
CXX = gcc
####################################################
################## MEXSUFFIX ################
MEXSUFFIX = mexa64
####################################################
################## Home of my matlab version #####
MATLABHOME = /home/tuebel/matlab
####################################################
################## Object_File_Declaration_Folder ################
OBJS_MEX = FFTW_build.o
OBJS_FFTW_FUNC = FFTW_func.o
ODIR=obj
_OBJ = $(OBJS_MEX) $(OBJS_FFTW_FUNC)
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
####################################################
################## Header_Files ################
# Header for mex
DIR_MEX_HEADER = /home/tuebel/matlab/extern/include
_DEPS_MEX = mex.h
DEPS_MEX = $(patsubst %,$(DIR_MEX_HEADER)/%,$(_DEPS_MEX))
# Header for fftw3
DIR_FFTW_HEADER = /usr/local/include
_DEPS_FFTW = fftw3.h
DEPS_FFTW = $(patsubst %,$(DIR_FFTW_HEADER)/%,$(_DEPS_FFTW))
####################################################
################## Library_Files ################
# Libraries for mex
MEX_LIB = /home/tuebel/matlab/bin/glnxa64/libmex.so
# Libraries for FFTW
FFTW_LIB = /usr/local/lib/libfftw3.a
# Libraries for math_function
MATH_LIB = -lm
####################################################
################## Flags ################
# MEXFLAGS = -shared -Wl,--no-undefined -Wl,-rpath-link,$(MATLABHOME)/bin/glnxa64 -L$(MATLABHOME)/bin/glnxa64 -lmex -lmat -lmx -lm
MEXFLAGS = -shared -Wl,-rpath-link,$(MATLABHOME)/bin/glnxa64 -L$(MATLABHOME)/bin/glnxa64 -lmex -lmat -lmx -lm
COMPILERFLAGS = -fPIC -pthread -DMATLAB_MEX_FILE -ansi -D_GNU_SOURCE -fno-omit-frame-pointer -O3 -DNDEBUG
FFTW_FLAGS_INCLUDE = -I$(DIR_FFTW_HEADER)
MEX_FLAGS_INCLUDE = -I$(DIR_MEX_HEADER)
####################################################
#################### Final_Part ######################
TARGET = FFTW_MEX
all: $(TARGET)
echo ALL DONE
clean:
rm -f $(ODIR)/*.o
rm -f $(TARGET).mexa64
echo CLEAN DONE
$(ODIR)/%.o: %.c $(DEPS_MEX) $(DEPS_FFTW)
$(CXX) -c -o $# $< $(COMPILERFLAGS) $(MEX_FLAGS_INCLUDE) $(FFTW_FLAGS_INCLUDE)
# Final_Linking
$(TARGET) : $(OBJ) $(MATH_LIB) $(FFTW_LIB)
$(CXX) -o $#.$(MEXSUFFIX) $(MEX_FLAGS_INCLUDE) $(FFTW_FLAGS_INCLUDE) $^ $(MEXFLAGS)
####################################################
####################################################
####################################################
The idea is to make a FFTW using fftw3. The code works fine in the command window, but if I try to make it executable from matlab (.mexa64 file) it is not working. I get the following error message using make:
gcc -c -o obj/FFTW_build.o FFTW_build.c -fPIC -pthread -DMATLAB_MEX_FILE -ansi -D_GNU_SOURCE -fno-omit-frame-pointer -O3 -DNDEBUG -I/home/tuebel/matlab/extern/include -I/usr/local/include
gcc -c -o obj/FFTW_func.o FFTW_func.c -fPIC -pthread -DMATLAB_MEX_FILE -ansi -D_GNU_SOURCE -fno-omit-frame-pointer -O3 -DNDEBUG -I/home/tuebel/matlab/extern/include -I/usr/local/include
gcc -o FFTW_MEX.mexa64 -I/home/tuebel/matlab/extern/include -I/usr/local/include obj/FFTW_build.o obj/FFTW_func.o /usr/lib64/libm.so /usr/local/lib/libfftw3.a -shared -Wl,-rpath-link,/home/tuebel/matlab/bin/glnxa64 -L/home/tuebel/matlab/bin/glnxa64 -lmex -lmat -lmx -lm
/usr/lib64/gcc/x86_64-suse-linux/4.8/../../../../x86_64-suse-linux/bin/ld: /usr/local/lib/libfftw3.a(lt4-problem.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/usr/local/lib/libfftw3.a: error adding symbols: Bad value
collect2: error: ld returned 1 exit status
Makefile:92: recipe for target 'FFTW_MEX' failed
make: *** [FFTW_MEX] Error 1
Can someone help me out? This is my first Makefile and I would be glad for any help... I am also glad for corrections to the Makefile...
Thanks a lot!
It is a bit unclear what you mean by an "executable" .mexa64 file.
MATLAB's mex compiler will let you compile C/C++ code with MATLAB libraries into a mex file (with 64 bit architecture for you here) that you can then "execute" via MATLAB's command line. This seems to be what you have gotten to work already.
However, if you want to have a stand alone "executable" outside of MATLAB, you need to work with MATLAB's mcr compiler (see the reference here). There are flags that you can set in the process to be build an object file which you can then link with later on with your makefile as you are trying to now.
So, don't mix mex compiled files which are runnable within MATLAB and mcr compiled code that is executable outside of it.
Apart from this, gcc is complaining that there is no main() function. I don't see one in your code here either, but you need a main() function for a standalone executable.
For some reason I have having an issue compiling a shared object that uses ncurses. Even though I include and link with -lncurses, compiling the .so file fails. Please advise.
#include <string.h>
#include "../include/mod_curse.h" /* Includes ncurses.h and friends */
int OnConsoleCmd(McapiS *API, ArgS *CmdArgs) /* Just ignore these, they're included in mod_curse.h */
{
if(!strcmp(CmdArgs->Data, "help"))
{
API->BPrintf(STD, "\n-- mod_curse.so --\n");
return 0;
}
}
int OnLoad(McapiS *API, va_list Args)
{
initscr(); /* These are the problems */
}
/* Time to clean up and unload the module */
int OnDeload(McapiS *API, va_list Args)
{
endwin();
}
Here is the Makefile:
CC = clang
CFLAGS = -Wall -fPIC
# Object Files
OBJ = mod_curse.o
# Header Files
INCLUDE = include/mod_curse.h
# Main Module
mod_setup.so: $(OBJ) $(INCLUDE)
$(CC) -shared -Wl,-soname,mod_curse.so,--no-undefined -o ../../mod_curse.so -lncurses $(OBJ)
# Source Files
mod_curse.o: src/mod_curse.c $(INCLUDE)
$(CC) $(CFLAGS) -c src/mod_curse.c
clean:
rm $(OBJ)
Here are the errors:
3 warnings generated.
clang -shared -Wl,-soname,mod_curse.so,--no-undefined -o ../../mod_curse.so -lncurses mod_curse.o
mod_curse.o: In function `OnLoad':
src/mod_curse.c:(.text+0x81): undefined reference to `initscr'
mod_curse.o: In function `OnDeload':
src/mod_curse.c:(.text+0xb1): undefined reference to `endwin'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [mod_setup.so] Error 1
I needed to change my make command to have -lncurses appear after $(OBJ).