Reputation: 10153
I've written an OpenCL kernel in a .cl
file. It attempts to #include
several headers.
Its compilation fails, since the included header files are "not found".
I am aware that clBuildProgram
can take the -I dir
option, which adds the directory dir
to the list of directories to be searched for the header files.
In the khronus site forum this post http://www.khronos.org/message_boards/viewtopic.php?f=37&t=2535 talks about the issue.
They propose to use clCreateProgramWithSource
which specifies all sources (including .h files).
I have a questions regarding this issue:
clBuildProgram
vs. clCreateProgramWithSource
, as described above)clCreateProgramWithSource
how does the compiler know what to include? I mean, which source stands for which included file name?clBuildProgram
and there are several directories with include files, how do I specify them?Upvotes: 12
Views: 22924
Reputation: 4874
There is one more dirty trick: you should emulate include yourself (i. e. something like manual amalgamation). It is not very clear for coding, but it works if your OpenCL compiler doesn't support (or supports incorrectly) -I
directives. This approach is not perfect (for example, you lose syntax highlighting), but can help for old or buggy OpenCL compilers.
Small simple example of this possibility:
std::string load_file(const std::string &file_name, int max_size = 0x100000)
{
FILE *fp = fopen(file_name.c_str(), "rb");
if (!fp)
{
// print some error or throw exception here
return std::string();
}
char *source = new char[max_size];
size_t source_size = fread(source, 1, max_size, fp);
fclose(fp);
if (!source_size)
{
delete[] source;
// print some error or throw exception here
return std::string();
}
std::string result(source);
delete[] source;
return result;
}
// errors checks are omitted for simplification
std::string full_source = load_file("header.h");
full_source += load_file("source.cl");
const char *source_ptr = full_source.c_str();
size_t source_size = full_source.size();
cl_int_status = CL_SUCCESS;
cl_program program = clCreateProgramWithSource(context, 1,
(const char **)&source_ptr, (const size_t *)&source_size, &ret);
// check status for CL_SUCCESS here
// now you have your program (include + source)
Upvotes: 1
Reputation: 3012
OpenCL requires you use clCreateProgramWithSource()
followed by clBuildProgram()
.
ClCreateProgramWithSource()
creates and returns a cl_program
object.
That cl_program
object is input into clBuildProgram()
.
clBuildProgram()
allows you to specify compiler options which include the include file
directories. In your case, for header file includes, it will be something like the string:
-I myincludedir1 -I myincludedir2 ...
The compiler used is the internal OpenCL compiler in the OpenCL SDK you are using. So if you are using AMD's SDK, the AMD OpenCL compiler that is part of their OpenCL SDK will be used. Likewise for Nvidia or Intel.
Its important to check the OpenCL status code for ALL OpenCL function calls.
This is mandatory for clCreateProgramWithSource()
and clBuildProrgam()
to get
any compiler errors or messages. There is a whole other bit code to write
to get the size of the messages and then retrieve the messages themselves.
Upvotes: 12
Reputation:
The Nvidia OpenCL device drivers have a bug when using -I with a certain number of includes and code length. AMD and Intel don't have this problem. My solutions is to instead concatenate all the .cl files into one large one at runtime. The disadvantage of this is that in debugging code the line number of the error corresponds to the concatentated .cl file and not in the individual .cl files.
I doubt Nvidia will ever fix this. They don't care about OpenCL much anymore.
Upvotes: 4