[C]undefined reference while compiling openCL program - c

I'm trying to compile something to try out openCl, but i'm having a few problems..
Here the code
prova.c
#include <stdio.h>
#include <CL/opencl.h>
#include "Utils\util.h"
#include <malloc.h>
int main(){
cl_int error = 0; // Used to handle error codes
cl_int max_platforms = 1; // The maximum number of platforms
cl_uint adviable_platforms = 0; //The adviable number of platforms
cl_platform_id* platform;
error = clGetPlatformIDs(0, NULL, &adviable_platforms);
if(adviable_platforms == 0)
{
printf("No adviable platforms.\n");
return -1;
} else {
platform = (cl_platform_id*)malloc(adviable_platforms * sizeof(cl_platform_id));
}
error = clGetPlatformIDs(adviable_platforms, platform, NULL);
printf("clGetPlatformIDs: %s\n", clErrorString(error));
return 0;
}
I'm compiling on win 7 64 with mingw32. The opencl headers are in the include directory of mingw while utils.h(inside the directory Utils inside the directory of prova.c) defines clErrorString(that simply convert the error into a more human readable string).
To compile i use
gcc -L\Utils prova.c
But i always get
C:\[stuff]\ccEjYQbj.o:prova.c:(.text+0x42): undefined reference to 'clGetPlatformIDs#12'
C:\[stuff]\ccEjYQbj.o:prova.c:(.text+0x8d): undefined reference to 'clGetPlatformIDs#12'
C:\[stuff]\ccEjYQbj.o:prova.c:(.text+0x9e): undefined reference to 'clErrorString'
I'm not so good with compilers, so i image i'm missing something, but i really don't know what..
EDIT:
Sincerely, i tried every command come to my mind. using -L to include directories, -l to link to files, using ar..
This is the last "script" i tried
set PATH=%PATH%;C:\Python26;C:\MinGW\bin;C:\MinGW\lib
cd Utils
gcc -c util.c -l"C:\Program Files (x86)\AMD APP\lib\x86_64\libOpenCL.a" -o util.o
ar rcs libutil.a util.o
cd..
pause
gcc -c prova.c -l"Utils\libutil.a" -o prova.exe
pause
EDIT2:
#echo off
set PATH=%PATH%;C:\Python26;C:\MinGW\bin;C:\MinGW\lib
cd Utils
gcc -Wall -c util.c -L"C:\Program Files (x86)\AMD APP\lib\x86_64\" -o util.o
ar rcs libutil.a util.o
cd..
pause
gcc -Wall -c prova.c -L"C:\Program Files (x86)\AMD APP\lib\x86_64\" -l"Utils\libutil.a" -o prova.exe
pause
No errors, the only warning is max_platform is unused. Then i find util.o and libutil.a(size 5kb) in Utils and prova.o(size 1kb). If i try to run prova.o, it says that the file version is not compatible with the current windows version, check the system version (x86 or x64) and contact the software distributor

Try something like this:
set PATH=%PATH%;C:\Python26;C:\MinGW\bin;C:\MinGW\lib
cd Utils
gcc -W -Wall -c util.c -o util.o
ar rcs libutil.a util.o
cd..
gcc -W -Wall -c prova.c -o prova.o
gcc -o prova.exe prova.o Utils\libutil.a
# Using a standard library
gcc -o prog.exe myprog.o -lzip # e.g. /usr/lib/libz.a
# Using a nonstandard library
gcc -o prog.exe myprog.o -lfoo -L/tmp/libfoo # uses /tmp/libfoo/libfoo.a
gcc -o prog.exe myprog.o /tmp/libfoo/libfoo.a # same effect
In general:
Compile single source files with -c:gcc -c myfile.c -o myfile.o.This creates object files.
Link all the object files to an executable (or shared library):gcc -o prog.exe myfile.o yourstuff.o sha257.o
You can combine object files into a static library, which you treat just like a single object file when linking:ar rcs libcoolstuff.a yourstuff.o sha257.ogcc -o prog.exe myfile.o libcoolstuff.aAlternatively:gcc -o prog.exe myfile.o -lcoolstuffThe latter syntax (automatic library linking with -l) requires either libcoolstuff.a or libcoolstuff.so to be findable in the library path (which you can amend with -L at linktime).

Related

Shared library disparity between Linux CentOS 7 and Ubuntu 20.04.1 LTS

I am porting a project written in C from a CentOS 7 (Core) to an Ubuntu 20.04.1 LTS (Focal Fossa) system. The project relies heavily on the <cpuset.h> library, and compiles and executes correctly on the CentOS system. However, when I try to use functions from cpuset.h on the Ubuntu system, I get 'undefined reference' errors.
The following code, stored in file test.c, compiles and runs correctly on CentOS:
#define _GNU_SOURCE
#include<stdio.h>
#include <cpuset.h>
int main(){
int x = cpuset_version();
printf("cpuset lib version: %d\n",x );
return 0;
}
How I compile:
gcc -Wall -O2 -std=gnu99 -g -lcpuset test.c -o test
Output:
[xxxx#CentOS]$ ./test
cpuset lib version: 3
However, when I try to compile the same test.c file on the Ubuntu system, I get this error:
xxxx#Ubuntu:$ gcc -Wall -O2 -std=gnu99 -g -lcpuset test.c -o test
/usr/bin/ld: /tmp/ccpxlk4F.o: in function `main':
test.c:8: undefined reference to `cpuset_version'
collect2: error: ld returned 1 exit status
Furthermore, this is not limited to the <cpuset.h> library. I tried to use a simple function from <pthread.h> and it also gave me the same error. Can anyone help with identifying why I cannot use shared libraries on the Ubuntu system? Thanks in advance
Since OP's issue is wrong order of parameters to GCC (many guides do show an incorrect order!), as discussed in the comments to the question, I believe showing a minimal Makefile to handle these is warranted:
CC := gcc
CFLAGS := -Wall -O2 -g
LDFLAGS := -lcpuset
TARGETS := test
.PHONY: all clean
all: $(TARGETS)
clean:
rm -f *.o $(TARGETS)
%.o: %.c
$(CC) $(CFLAGS) -c $^
test: test.o
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $#
Note that the indentation in Makefiles must use Tabs and not spaces. Since this forum converts Tabs to spaces, you will need to fix the above makefile, for example by running sed -e 's|^ *|\t|' -i Makefile.
If you want to compile say foo.c directly to an executable, the recipe is
foo: foo.c
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $#
You only need to run make (it defaults to using the Makefile in the current directory, and the default target is the first one, above the one named all), to recompile the TARGETS (here, test, but you can supply more by just adding them space-separated to the line).
You can also run make clean test to rebuild test from "scratch", i.e. removing all temporary files and all targets first.
You can override variables like CFLAGS by simply supplying them on the command line; for example, make CFLAGS="-Wall -Wextra -Os" clean all to recompile everything with different compilation flags.

Ocaml/C interop using bigarray: 'undefined symbol: caml_ba_alloc'

I'm trying to compile a 'Hello World'-level Ocaml/C interop program that uses bigarray. I'm getting an error about undefined symbol: caml_ba_alloc (details below). It seems like it should be provided by bigarray.h.
Here are my files:
wrap_mylib.c:
#include <caml/bigarray.h>
#include <caml/mlvalues.h>
#include <caml/memory.h>
CAMLprim value caml_fn(value x) {
float* result = malloc(sizeof(float));
long dims[] = {1, 1};
return caml_ba_alloc(CAML_BA_NATIVE_INT, 2, result, dims);
}
mylib.ml:
external ext_caml_fn : int -> (float, Bigarray.float32_elt, Bigarray.c_layout) Bigarray.Array2.t
= "caml_fn" ;;
Makefile:
wrap_mylib.o: wrap_mylib.c
gcc -c wrap_mylib.c
another_wrapper.so: wrap_mylib.o
cc -shared -o another_wrapper.so wrap_mylib.o
mylib.mli: mylib.ml
ocamlc -i $< > $#
mylib.cmi: mylib.mli
ocamlc -c $<
mylib.cmo: mylib.ml mylib.cmi
ocamlc -c $<
mylib_test: mylib.cmo another_wrapper.so
ocamlc -linkall -o mylib_test mylib.cmo another_wrapper.so
clean:
rm *.cma *.cmo *.cmi *.cmx *.cmxa *.mli *.o *.a *.so
Here is the output when I try to compile mylib_test:
$ make mylib_test
ocamlc -i mylib.ml > mylib.mli
ocamlc -c mylib.mli
ocamlc -c mylib.ml
gcc -c wrap_mylib.c
cc -shared -o another_wrapper.so wrap_mylib.o
ocamlc -linkall -o mylib_test mylib.cmo another_wrapper.so
File "_none_", line 1:
Error: Error on dynamically loaded library: ./another_wrapper.so: ./another_wrapper.so: undefined symbol: caml_ba_alloc
Makefile:17: recipe for target 'mylib_test' failed
make: *** [mylib_test] Error 2
Environment
OS: Ubuntu 18.04.2 LTS (Bionic Beaver)
$ ocaml --version
The OCaml toplevel, version 4.05.0
Thank you!
Files like bigarray.h define things that are useful at compile time. But your problem is a link-time problem. You need to find the library that contains the function you're looking for and include it in the link step.
If I use ocamlopt (native code implementation) and use ordinary object files (OCaml .cmx and C .o) rather than a shared library, I can get things to link up like this:
$ ocamlopt -c mylib.ml
$ gcc -I $(ocamlc -where) -c wrap_mylib.c
$ ocamlopt -o mylib_test wrap_mylib.o mylib.cmx
This produces an executable mylib_test that I can run:
$ ./mylib_test
$
Of course nothing happens when I run the executable because there is no top-level code in your file mylib.ml. So this is just testing whether things will link up OK.
I hope this is helpful.
Answering my own question. Here's how I was able to get it to work. Compile mylib_test by linking bigarray.cma:
ocamlc -linkall -o mylib_test mylib.cmo another_wrapper.so bigarray.cma
Then run with:
LD_LIBRARY_PATH=. ./mylib_test
The LD_LIBRARY_PATH=. is necessary for it to find the shared library another_wrapper.so in the same directory.
According to https://caml.inria.fr/pub/docs/manual-ocaml/libbigarray.html bigarray is now part of the standard library and so linking bigarray.cma should only be necessary when using the legacy compatibility library. Possibly my version of the standard library is old.

Cannot find -lCommunication collect2: error: ld returned 1 exit status

I do not know gcc and c well. In my /home/pi/Desktop/intern/adis16227_generic directory I have following 5 files.
ADIS16227.c
ADIS16227.h
Communication.c
Communication.h
main.c
main.c
#include<stdio.h>
#include "Communication.h" // Communication definitions.
int main() {
printf("hello!!\n");
unsigned char status = 0;
status = SPI_Init(0, 1000000, 1, 1);
printf("%u", status);
return 0;
}
Run command:
$ sudo gcc -L /home/pi/Desktop/intern/adis16227_generic main.c -lCommunication
Error:
/usr/bin/ld: cannot find -lCommunication
collect2: error: ld returned 1 exit status
Question:
What I am missing here?
What do I need to run the code?
-l is for libraries, and you never built a library from your Communication.c. The simplest solution is just add Communication.c to your compiler command line.
For larger projects, compile each translation unit separately with the -c switch like this:
gcc -c -Wall -Wextra -pedantic -omain.o main.c
gcc -c -Wall -Wextra -pedantic -oCommunication.o Communication.c
and so on ... (as a suggestion, I added some common warning options here, they help you spot errors)
The resulting .o files are object code. That's already compiled machine code, but with meta-information needed for a linker to link it with other object code into a complete executable.
Then link them all with one command:
gcc -oprogram main.o Communication.o
If you actually want a library from -- say -- Communication.c and ADIS16227.c, you could compile both to object code:
gcc -c -Wall -Wextra -pedantic -oCommunication.o Communication.c
gcc -c -Wall -Wextra -pedantic --oADIS16227.o ADIS16227.c
and then use ar to create a static library from them:
ar rcs libCommunication.a Communication.o ADIS16227.o
Then your initial compiler command would work (with the -lCommunication switch).
Final piece of advice: Never compile as root. This is completely unnecessary. So remove your sudo here.
those options:
-L /home/pi/Desktop/intern/adis16227_generic -lCommunication
suggest that the linker should find libCommunication.a (or .so) in the /home/pi/Desktop/intern/adis16227_generic directory.
But there are only sources in this directory. The linker won't build the sources of your "Communication" library for you.
So you could build the library and link with it:
gcc -c ADIS16227.c Communication.c
ar r libCommunication.a ADIS16227.o Communication.o
but maybe the fastest & quickest way to achieve a successful build would be:
sudo gcc -o main *.c
so it compiles all the files of the directory into the executable called main
Of course, it makes compilation times longer, but maybe it's not noticeable.
First move into the /home/pi/Desktop/intern/adis16227_generic directory:
cd /home/pi/Desktop/intern/adis16227_generic
Then, compile the source:
gcc ADIS16227.c Communication.c main.c -I .
You can now run your compiled program (called by default a.out):
./a.out
You have to compile separatedly files and then compile main with related obj file.
gcc -c Communication.c Communication.h
gcc main.c Communication.o -o main

Compiling on RaspberryPi by using make

When I use make to compile the RaspberryPi's source code, the error happens like this:
"bmp180.c:(.text+0xe8): undefined reference to `bcm2835_i2c_write'"
However, I have used the "-l bcm2835", the makefile as follow:
#makefile
bmp: main.o bmp180.o
gcc -o bmp main.o bmp180.o
main.o: main.c bmp180.h
gcc -c main.c -l bcm2835.h
bmp180.o: bmp180.c bmp180.h
gcc -c bmp180.c -l bcm2835.h
clear:
rm -f main.o bmp180.o
You have -l bcm2835.h in your Makefile. The name of the library is simply bcm2835. Files ending with .h are files meant to be #include'd in your C source; they are not dynamic shared libraries.
Additionally, shared libraries are required at the link stage, not the compile stage; you will need to add -l bcm2835 to the linking step:
bmp: main.o bmp180.o
gcc -o bmp main.o bmp180.o -l bcm2835
The -l arguments in your compile steps are effectively no-ops (but they won't hurt anything).

Exec format error when compiling C file for Python extension

I am trying to extend python using a simple C file. I succeeded in creating my own python module, but I also need the C file itself to compile and run as a standalone executable. I can successfully compile it, but when I try to run it I get the error "cannot execute binary file: Exec format error".
Here is my C source file (hellomodule.c):
#include <Python.h>
void print_hello(const char* name){
printf("Hello %s!\n", name);
}
//Only used by Python
static PyObject*
say_hello(PyObject* self, PyObject* args)
{
const char* name;
if (!PyArg_ParseTuple(args, "s", &name))
return NULL;
//printf("Hello %s!\n", name);
print_hello("World");
Py_RETURN_NONE;
}
//Only used by Python
static PyMethodDef HelloMethods[] =
{
{"say_hello", say_hello, METH_VARARGS, "Greet somebody."},
{NULL, NULL, 0, NULL}
};
//Only used by Python
PyMODINIT_FUNC
inithello(void)
{
(void) Py_InitModule("hello", HelloMethods);
}
int main(){
print_hello("World");
}
I can "successfully" compile it without any errors or warnings with the following:
gcc -I /usr/include/python2.7 -c hellomodule.c -o hellomodule
After making the "hellomodule" file executable, I run it and get the error:
-bash: ./hellomodule: cannot execute binary file: Exec format error
Why would this be causing such an error?
You are trying to execute an object file, that is not an executable. To compile your code as a module you need something like
gcc -Wall -Werror -Wextra -O2 -I/usr/include/python2.7 \
-shared hellomodule.c -o hellomodule.so -lpython2.7
but to link correctly to everything and add all the possible include directories there is a script called python-config you just need to invoke it like this
gcc -Wall -Werror -Wextra -O2 `python-config --includes` \
-shared hellomodule.c -o hellomodule.so `python-config --libs`
and even better, the script providesCFLAGS and LDFLAGS too, so finally
gcc -Wall -Werror -Wextra -O2 `python-config --cflags` \
-shared hellomodule.c -o hellomodule.so `python-config --ldflags`
and then, copy the resulting file to /usr/lib/python2.7/site-packages.
After that, you can load the module in a python script like this
import hellomodule
Object files are intermediate binary files used ultimately by the linker (ld probably) to produce the final binary. A python module has no main() function and it has to be a runtime loadable shared object which exports some predefined symbols that the python interpreter will use to load the module into the python script/program.
Note: To correctly do this and not die trying create a Makefile, like this
CFLAGS = `python-config --cflags` -Wall -Werror # add more if needed
LDFLAGS = `python-config --ldflags` # add more if needed
OBJS = hellomodule.o # add more if needed
all: $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -shared -o modulename.so $(OBJS)
%.o: %.c
$(CC) -c $(CFLAGS) $<
ensure that you use tabs instead of spaces for indentation, and then run make in the same directory where the Makefile and the source files are.

Resources