web-dev-qa-db-fra.com

la bibliothèque est liée mais la référence est indéfinie

J'essaie de compiler un programme openCL sur Ubuntu avec une carte NVIDIA qui fonctionnait une fois auparavant,

#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;
}

Je le compile comme si,

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

et j'obtiens ce résultat

/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

mais nm -D /usr/lib/nvidia-current/libOpenCL.so me dit que libOpenCL.so contient au moins clGetPlatformIDs

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

Est-ce que je manque quelque chose?.

30
user615457

De la page de manuel gcc:

   -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.

Essayez donc de spécifier le -lOpenCL après l'argument de fichier dans votre commande de compilation.

Vous recherchez également des symboles dans libOpenCL.so, qui est un fichier de bibliothèque partagée. Avec votre commande, vous liez votre programme à une bibliothèque statique, au format libOpenCL.a.

24
Geoffroy

lorsque vous créez un lien, l'ordre de vos bibliothèques et de vos fichiers source fait la différence. par exemple pour votre cas,

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

les fonctions définies dans la bibliothèque OpenCL peuvent ne pas être chargées, car rien ne les a précédées pour demander une consultation. cependant si vous utilisez,

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

alors toutes les demandes de fonctions seront trouvées dans la bibliothèque OpenCL et elles seront chargées.

29
user995502

Vous pouvez également ajouter l'en-tête et le chemin de la bibliothèque à vos variables globales.

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

Vous pouvez également essayer de définir

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

Il devrait être possible de courir maintenant

g++ opencl.cpp
0
Jesse