注意:这个问题与 OpenCL 本身无关......请检查最后一段以获取我的问题的简洁陈述。但提供一些背景:
我正在编写一些使用 OpenCL 的 C++ 代码。我喜欢将 OpenCL 内核的源代码保存在自己的文件中,以便于编码和维护(而不是直接将源代码作为字符串常量嵌入到关联的 C++ 代码中)。这不可避免地会导致一个问题,即在分发二进制文件时如何将它们加载到 OpenCL 运行时中——理想情况下,OpenCL 源代码包含在二进制文件中,这样二进制文件就不需要位于特定位置在某些目录结构中了解 OpenCL 源代码的位置。
我想将 OpenCL 文件作为字符串常量包含在某处,并且最好不使用额外的构建步骤或外部工具(为了跨编译器/跨平台的易用性......即,不xxd
等)。我以为我偶然发现了一种基于第二个答案的技术this https://stackoverflow.com/questions/1415538/using-include-to-load-opencl-code线程,像这样:
#define STRINGIFY(src) #src
inline const char* Kernels() {
static const char* kernels = STRINGIFY(
#include "kernels/util.cl"
#include "kernels/basic.cl"
);
return kernels;
}
请注意,我不想嵌入STRINGIFY
如果可能的话,在我的 OpenCL 代码中添加宏(如上面引用的 SO 问题中所做的那样)。现在,这在 Clang/LLVM 编译器上运行得很好,但 GCC 却死得很惨(“未终止的参数列表调用宏 STRINGIFY”以及与 .cl 文件内容相关的各种语法“错误”出现)。所以,显然这种精确的技术不能跨编译器使用(没有尝试过 MSVC,但我希望它也能在那里工作)...我怎样才能最小化它以使其跨编译器工作?
总之,我想要一种符合标准的技术,将文件的内容作为 C/C++ 字符串常量包含在内,而无需调用外部工具或用无关代码污染文件。有想法吗?
EDIT:正如 Potatoswatter 指出的那样,上述行为是未定义的,因此不涉及接触要字符串化的文件的真正的交叉编译器预处理器技术可能是不可能的(第一个找出令人发指的黑客的人那does大多数/所有编译器的工作都会得到答案点)。出于好奇,我最终按照第二个回复中的建议进行了操作here https://stackoverflow.com/questions/1415538/using-include-to-load-opencl-code...也就是说,我添加了STRINGIFY
直接宏到我包含的 OpenCL 文件:
In somefile.cl
:
STRINGIFY(
... // Lots of OpenCL code
)
In somefile.cpp
:
#define STRINGIFY(src) #src
inline const char* Kernels() {
static const char* kernels =
#include "somefile.cl"
;
return kernels;
}
这在我尝试过的编译器中有效(Clang 和 GCC 也是如此,因为它在宏内部没有预处理器指令),并且至少在我的上下文中不是太大的负担(即,它没有)不干扰语法突出显示/编辑 OpenCL 文件)。像这样的预处理器方法的一个特点是,由于相邻的字符串被连接起来,因此您可以编写
inline const char* Kernels() {
static const char* kernels =
#include "utility_functions.cl"
#include "somefile.cl"
;
return kernels;
}
并且只要 STRINGIFY 宏都在.cl
文件中,字符串被连接起来,允许您模块化您的 OpenCL 代码。