1
votes

I'd like to have a few host helper functions written in regular old C to be include'd in a .cu file which runs some of that host code and also defines and calls kernel functions. I have no knowledge of makefiles and don't have a good feel for multi-file projects in general, and can't understand why the following works with a .c extension but fails with a .cu extension.

A.h

void sayhello();

A.c:

#include "A.h"
#include <stdio.h>
void sayhello() {
    printf("Hello from A\n");
}

B.c:

#include "A.h"
int main(int argc, char * argv) {
    sayhello();
    return 0;
}

B.cu

#include "A.h"
int main(int argc, char * argv[]) {
    sayhello();
    return 0;
}

When I compile A.c everything works fine:

$ nvcc -arch compute_30 -code sm_30 -o test B.c A.c  
$ ./test  
Hello from A

But when trying to compile B.cu the linker can't find sayhello()

$ nvcc -o test B.cu A.c  
/tmp/tmpxft_000017bb_00000000-16_B.o: In function 'main':
tmpxft_000017bb_00000000-4_B.cudafe1.cpp:(.text+0x26): undefined reference to 'sayhello()'
collect2: error: ld returned 1 exit status

Why isn't it finding sayhello(), what's the difference between these compilations, and is there a solution to compiling code of this structure?

2

2 Answers

3
votes

CUDA uses a C++ compiler to compile .cu files. Therefore, it expects that all functions referenced in .cu files have C++ linkage unless explicitly instructed otherwise. And in your case, you must explicitly instruct the C++ compiler otherwise.

You should find that modifying your code like this:

extern "C" { 
#include "A.h"
}
int main(int argc, char * argv[]) {
    sayhello();
    return 0;
}

will fix the problem as it will instruct the compiler to expect C linkage for your C functions, not C++ linkage.

-3
votes

You need to use __host__ __device__ decoration on the sayhello function.

Also, include cuda_runtime.h in A.h