Shared library creation?

Hi guys,

I have just learn how to create shared libraries in linux through the ‘Program Libraries HOWTO’.

For now, I’ve been messing around with CUDA’s template project to turn it into a shared library.

So far what I’ve done:

  1. Change main() in template.cu to cudamain().
  2. I managed to turn it into a static library (a.a) with 'nvcc -lib template.cu -I …/…/common/lib.
  3. Can’t get another program to compile with it. It errors: missing symbol ‘cudamain’ even though it recognises a.a.

However, what I really want to know is how do I make nvcc create a shared library. Thanks :mellow:

nvcc --help says that --shared will produce a shared library. I’ve never tried it as I use CMake + FindCUDA.cmake for compiling which handles all the internal compile commands needed to create the shared library.

You may need to declare cudamain as

extern "C" cudamain() { ... }

in your libs header file if the program you are linking your library to is C++.

If you are on a 64-bit Linux system, you may also need to pass the -fPIC option through to the host compiler:

       nvcc --ptxas-options=-v --compiler-options '-fPIC' -o mylib.so --shared mykernel.cu

Thanks guys. However, it still doesn’t answer my question on how do I generate the shared library. Is there anyone I can ask regarding this matter?

EDIT: Found this but have not tried it out.

http://www.gpgpu.org/forums/viewtopic.php?p=16723

Did you read my suggestion to use --shared? Did you read seibert’s post where a full command line was given?

To reiterate:

$ nvcc --shared -o libtest.so test.cu --compiler-options '-fPIC' 

$ file libtest.so

libtest.so: ELF 64-bit LSB shared object, AMD x86-64, version 1 (SYSV), not stripped

$ ldd libtest.so 

        libcudart.so => /opt/cuda/lib/libcudart.so (0x00002ae61beda000)

        libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00002ae61c117000)

        libm.so.6 => /lib64/libm.so.6 (0x00002ae61c417000)

        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00002ae61c69b000)

        libc.so.6 => /lib64/libc.so.6 (0x00002ae61c8a9000)

        libdl.so.2 => /lib64/libdl.so.2 (0x00002ae61cbfc000)

        libpthread.so.0 => /lib64/libpthread.so.0 (0x00002ae61ce01000)

        librt.so.1 => /lib64/librt.so.1 (0x00002ae61d01b000)

        /lib64/ld-linux-x86-64.so.2 (0x0000003a9ea00000)

If this is not what you are asking for, then please clarify what you mean by “how do I generate the shared library”

Hey guys, this is my attempt at it. Errorrreed. Thanks for the help.

hpr@hpr-xps:~/NVIDIA_CUDA_SDK/projects$ cp -rf template/ templatelib

hpr@hpr-xps:~/NVIDIA_CUDA_SDK/projects$ cd templatelib/

hpr@hpr-xps:~/NVIDIA_CUDA_SDK/projects/templatelib$ vim template.cu

----------- I changed main() to cudamain() 

hpr@hpr-xps:~/NVIDIA_CUDA_SDK/projects/templatelib$ nvcc --shared -o libtest.so template.cu template_kernel.cu template_gold.cpp --compiler-options '-fPIC' -I ../../common/inc/ -I /usr/local/cuda/include/

template_kernel.cu(68): error: identifier "CUT_BANK_CHECKER" is undefined

1 error detected in the compilation of "/tmp/tmpxft_00002803_00000000-15_template_kernel.cpp1.ii".

hpr@hpr-xps:~/NVIDIA_CUDA_SDK/projects/templatelib$

Since you are using CUT_BANK_CHECKER, you need to specify the include (-I) and library directories (-L) for CUT. The makefile sets these so you can open it as an example.

This is from Evan Lezar with final bits from me to make it work

Zaki: This is what I had to do to make it work.

The gcc command above would error out with

gcc -o main main.c -lname_of_shared_library

In file included from main.c:2:

…/cuda_functions.h:2: error: expected identifier or ‘(’ before string constant

make: *** [main] Error 1

What I had to do was to create another cuda_functions.h for gcc, say name it cuda_functions_wo_extern_C.h

with the contents

my_function ( int my_parameter );

I have a very similar issue, but the fix I see posted above doesn’t seem to work.

Here is the command I am using:

nvcc -Xcompiler ‘-fPIC’ --shared -v myFile.cu -o output.so

However, when I use it, I get the following error:
error: relocation R_X86_64_32S against `a local symbol’ can not be used when making a shared object; recompile with -fPIC

The thread above says I need to create a .h file with a declaration of the external C function and include it in my .cu file. I have done this as follows:.

below is the code of myFile.h
#ifndef CUDA_IMAGELOADER_H
#define CUDA_IMAGELOADER_H
extern “C” void launch_cudaCalculations(dim3 grid, dim3 block, int sbytes, float* g_data, float* g_odata, int imgw, int imgh, int tilew, int radius, float threshold, float highlight);
#endif

below is the code snippet from myFile.cu:
#include “myFile.h”
extern “C” void launch_cudaCalculations(dim3 grid, dim3 block, int sbytes, float* in_dev_ptr, float* out_dev_ptr, int cols, int rows)
{ … do stuff … }

Now when I compile I get:
myFile.cu(61): error: more than one instance of overloaded function “launch_cudaCalculations” has “C” linkage

Any ideas?

Regarding the extern issue with gcc (zakim). I have since found that following definition in the .h file allows one to use a single file:

[codebox]// the following is needed to allow for the compilation with nvcc as well as gcc

ifdef __cplusplus

#define CHECK_EXT extern "C"

else

#define CHECK_EXT 

endif

CHECK_EXT void function_def ();[/codebox]

Thus, I have defined a macro, CHECK_EXT that is blank if a C compiler is used (as opposed to a C++ compiler). This macro is then prefixed to any function definitions.

As far as I can tell this is due to nvcc and gcc defaulting to either C or C++ compilation. If someone has a better explanations, it would be much appreciated.

@muffinman104: In order to compile with the -fPIC switch using nvcc , one needs to use the --compiler-options -fPIC -shared nvcc options.

For example, the following line is what I use to compile a shared library that is to be built using cublas:

nvcc --shared --compiler-options -fPIC -shared lib_cuda_blas_backend.cu -o libcuda_blas_backend.so -L/usr/local/cuda/lib -lcublas

The shared library libcuda_blas_backend.so can then be linked to another C program as normal.

Please let me know if anything is unclear or you have more questions.

Evan

Thank You for your suggestion.
I have used your this following command to create .so file.
nvcc --shared --compiler-options -fPIC -shared lib_cuda_blas_backend.cu -o libcuda_blas_backend.so -L/usr/local/cuda/lib -lcublas

replaced command -
/usr/local/cuda-7.0/bin/nvcc --shared -Xcompiler -fPIC -shared add.cu -o libcuda_add.so

While linking this file with c file i.e. main.c it showing error

Command-
gcc -o main main.c -llibadd.so

error-
/usr/bin/ld: cannot find -llibadd.so
collect2: ld returned 1 exit status

Please let me know where i am getting wrong.

usually with the -l option you don’t pass the “lib” prefix and the “.so” suffix of libary names. It would be

-ladd or -lcuda_add

Christian

Thank You. I have resolved the issue.