2
votes

Using nvcc I created an object file from my project with the following bash script:

nvcc -Xcompiler -std=c99 -dc src/interface.cu src/functions.cu
nvcc -dlink interface.o functions.o -o obj/link.o

In my obj folder I get a link.o file. I need to link this file to my Ada project using gprbuild. I can compile an Ada-Cuda project perfectly if I don't use the separate compilation mode of nvcc. But now, as I need the separate compilation mode, I have to find a way to link link.o with the rest of the project. This is the .gpr file:

project Test is
    for Languages use ("Ada");
    for Source_Dirs use ("src");
    for Object_Dir use "obj";
    for Exec_Dir use ".";

    for Main use ("main.adb");

    for Create_Missing_Dirs use "True";

    package Linker is
        for Default_Switches("Ada") use (
            "-L/usr/local/cuda/lib64",
            "-lcuda",
            "-lcudart",
            "-lcudadevrt",
            "-lstdc++",
            "-lm");

        for Leading_Switches("Ada") use (
            "link.o" -- Doesn't work
            );
    end Linker;
end Test;

This is the error I get

Bind
   [gprbind]      main.bexch
   [Ada]          main.ali
Link
   [link]         main.adb
/usr/local/opt/gnat-19.1-x86_64/bin/../libexec/gcc/x86_64-pc-linux-gnu/7.3.1/ld: main.o: in function `_ada_main':
main.adb:(.text+0x5): undefined reference to `bind_say_hello'
/usr/local/opt/gnat-19.1-x86_64/bin/../libexec/gcc/x86_64-pc-linux-gnu/7.3.1/ld: link.o: in function `__cudaRegisterLinkedBinary_45_tmpxft_0000404a_00000000_11_interface_cpp1_ii_f804fc64':
link.stub:(.text+0x50): undefined reference to `__fatbinwrap_45_tmpxft_0000404a_00000000_11_interface_cpp1_ii_f804fc64'
/usr/local/opt/gnat-19.1-x86_64/bin/../libexec/gcc/x86_64-pc-linux-gnu/7.3.1/ld: link.o: in function `__cudaRegisterLinkedBinary_45_tmpxft_0000404a_00000000_13_functions_cpp1_ii_e57d67fc':
link.stub:(.text+0x96): undefined reference to `__fatbinwrap_45_tmpxft_0000404a_00000000_13_functions_cpp1_ii_e57d67fc'
collect2: error: ld returned 1 exit status
gprbuild: link of main.adb failed
gprbuild: failed command was: /usr/local/opt/gnat-19.1-x86_64/bin/gcc main.o link.o b__main.o -L/usr/local/cuda/lib64 -lcuda -lcudart -lcudadevrt -lstdc++ -lm -L/home/cir_eti/Documents/test/multi_cu_file/obj/ -L/home/cir_eti/Documents/test/multi_cu_file/obj/ -L/usr/local/opt/gnat-19.1-x86_64/lib/gcc/x86_64-pc-linux-gnu/7.3.1/adalib/ -static-libgcc /usr/local/opt/gnat-19.1-x86_64/lib/gcc/x86_64-pc-linux-gnu/7.3.1/adalib/libgnat.a -ldl -Wl,-rpath-link,/usr/local/opt/gnat-19.1-x86_64/lib/gcc/x86_64-pc-linux-gnu/7.3.1//adalib -Wl,-z,origin,-rpath,/usr/local/cuda/lib64:$ORIGIN/obj:/usr/local/opt/gnat-19.1-x86_64/lib/gcc/x86_64-pc-linux-gnu/7.3.1/adalib -o /home/cir_eti/Documents/test/multi_cu_file//main
1
Unsure if gprbuild supports adding .o files. Would compiling with --lib to an .a file and then simply linking that with gprbuild solve the problem?flyx
Adding -v to the link args may show what it's doing with for Object_Dir use "obj"; and "link.o" which may show why it's not putting them together and finding your file. The actual linker command line is probably useful too.user_1818839
Haven’t used Linker’Leading_Switches. I’d be inclined to put link.o as the first entry in Linker’Default_Switches.Simon Wright
It seems that 'link.o' is being passed to the linker, according to the error message. The problem should be elsewhere, for example, some missing library.Gneuromante
So the problem was really simple... Adding just link.o wasn't enough (it contains only GPU code). I also had to link interface.o and functions.o. As adviced by @flyx I created a static library with all the .o needed in it. It works like a charm nowLouis Etienne

1 Answers

0
votes

I'm doing an interface to a DLL and the interface they give is via a C header-file, I have an autogenerated package from the spec; I'm adding the post-conditions and, in the private portion of the package, I put this Linker_Options pragma which instructs the linker to interface with the DLL. -- IIUC, you could use this to address your problem.

Package import_example is

    Bad_Return           : Exception;

    SUCCESS              : constant := 20007;
    NOT_INITIALIZED      : constant := 20008;
    ERROR                : constant := 20009;
    INVALID              : constant := 20010;

    Function Return_Report (Name : String; Value : unsigned ) return String is
        (Name & " should not return" & unsigned'Image(Value) & '.') with Inline;

    function item_1 return unsigned  -- some_c_header.h:249
      with Import   => True, 
      Convention    => C, 
      External_Name => "item_1",
      Post          => item_1'Result in
        SUCCESS | NOT_INITIALIZED | ERROR | INVALID
          or else raise Bad_Return with
            Return_Report("item_1", item_1'Result)
    ;

    function wait return unsigned  -- some_c_header.h:250
      with Import   => True, 
      Convention    => C, 
      External_Name => "wait",
      Post          => wait'Result in
        SUCCESS | NOT_INITIALIZED | ERROR 
          or else raise Bad_Return with
            Return_Report("wait", wait'Result)
    ;

Private
    Pragma Linker_Options( "-lsmcex" );
End import_example;