library is linked but reference is undefined
Asked Answered
B

4

40

I'm trying to compile an openCL program on Ubuntu with an NVIDIA card that worked once before,

#include <CL/cl.h>
#include <iostream>
#include <vector>

using namespace std;

int main() {
  cl_platform_id platform;
  cl_device_id device;
  cl_context context;
  cl_command_queue command_queue;
  cl_int error;

  if(clGetPlatformIDs(1, &platform, NULL) != CL_SUCCESS) {
    cout << "platform error" << endl;
  }

  if(clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, NULL) != CL_SUCCESS) {
    cout << "device error" << endl;
  }

  context = clCreateContext(NULL, 1, &device, NULL, NULL, &error);
  if(error != CL_SUCCESS) {
    cout << "context error" << endl;
  }

  command_queue = clCreateCommandQueue(context, device, 0, &error);
  if(error != CL_SUCCESS) {
    cout << "command queue error" << endl;
  }

  return 0;
}

I compile it like so,

g++ -I/usr/local/cuda/include -L/usr/lib/nvidia-current -lOpenCL opencl.cpp

and I get this result

/tmp/ccAdS9ig.o: In function `main':
opencl.cpp:(.text+0x1a): undefined reference to `clGetPlatformIDs'
opencl.cpp:(.text+0x3d): undefined reference to `clGetDeviceIDs'
opencl.cpp:(.text+0x65): undefined reference to `clCreateContext'
opencl.cpp:(.text+0x85): undefined reference to `clCreateCommandQueue'
collect2: ld returned 1 exit status

but nm -D /usr/lib/nvidia-current/libOpenCL.so tells me that libOpenCL.so at least contains clGetPlatformIDs

0000000000002400 T clGetKernelWorkGroupInfo
0000000000002140 T clGetMemObjectInfo
0000000000002e80 T clGetPlatformIDs
0000000000002de0 T clGetPlatformInfo
0000000000002310 T clGetProgramBuildInfo
00000000000022f0 T clGetProgramInfo
00000000000021f0 T clGetSamplerInfo

Am I missing something.

Botticelli answered 16/10, 2011 at 9:10 Comment(0)
S
31

From the gcc man page:

   -llibrary
   -l library
       Search the library named library when linking.  (The second alternative with the library as a separate argument is only for POSIX compliance and is not recommended.)

       It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified.  Thus, foo.o
       -lz bar.o searches library z after file foo.o but before bar.o.  If bar.o refers to functions in z, those functions may not be loaded.

       The linker searches a standard list of directories for the library, which is actually a file named liblibrary.a.  The linker then uses this file as if it had been specified
       precisely by name.

So try to specify the -lOpenCL after the file argument in your compile command.

You also search for symbols in libOpenCL.so, which is a shared library file. With your command you link your program agains a static library, in the format libOpenCL.a.

Salena answered 16/10, 2011 at 9:25 Comment(1)
The last remark about static linking isn't true. modern gcc versions on shared library platforms will prefer shared libraries over static libraries automatically, only falling back to static when either no shared version is found, or the -static option is specified.Pandybat
B
47

when you are linking, the order of your libraries and source files makes a difference. for example for your case,

g++ -I/usr/local/cuda/include -L/usr/lib/nvidia-current -lOpenCL opencl.cpp

functions defined in the OpenCL library might not be loaded, since there nothing before them asking for a look-up. however if you use,

g++ opencl.cpp -I/usr/local/cuda/include -L/usr/lib/nvidia-current -lOpenCL  

then any requests for functions will be found in the OpenCL library and they will be loaded.

Bagatelle answered 28/10, 2011 at 21:22 Comment(1)
The order. The order is the key. Thank you.Veratrine
S
31

From the gcc man page:

   -llibrary
   -l library
       Search the library named library when linking.  (The second alternative with the library as a separate argument is only for POSIX compliance and is not recommended.)

       It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified.  Thus, foo.o
       -lz bar.o searches library z after file foo.o but before bar.o.  If bar.o refers to functions in z, those functions may not be loaded.

       The linker searches a standard list of directories for the library, which is actually a file named liblibrary.a.  The linker then uses this file as if it had been specified
       precisely by name.

So try to specify the -lOpenCL after the file argument in your compile command.

You also search for symbols in libOpenCL.so, which is a shared library file. With your command you link your program agains a static library, in the format libOpenCL.a.

Salena answered 16/10, 2011 at 9:25 Comment(1)
The last remark about static linking isn't true. modern gcc versions on shared library platforms will prefer shared libraries over static libraries automatically, only falling back to static when either no shared version is found, or the -static option is specified.Pandybat
J
6

In my case I compiled a c++ application but linked a C library. The included header file for that lib did not specify the function prototypes as extern "C" so the linker was searching for a decoarated function name instead of the plain C name. Specifying extern "C" around the C header includes solved this problem for me.

extern "C" {
#include "cheader.h"
}
Jackinthepulpit answered 6/3, 2023 at 9:32 Comment(3)
You could include a piece of code to demonstrate your answer.Justifiable
thanx I added some sample codeJackinthepulpit
thank you, my saviour. you just unblocked me after 3+ of trying everything with the linker..Genuflection
I
0

Alternatively you can add the header and library path to your global variables.

export CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:/usr/local/cuda/include
export LIBRARY_PATH=$LIBRARY_PATH:/usr/lib/nvidia-current

You can also try to set

export PATH=$PATH:/usr/local/cuda/bin

It should be possible to run now

g++ opencl.cpp
Inquest answered 10/3, 2016 at 19:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.