Примечание: этот вопрос не имеет ничего общего с OpenCL как таковым ... проверьте последний абзац, чтобы найти краткое изложение моего вопроса. Но чтобы предоставить некоторую предысторию:
Я пишу код на C ++, который использует OpenCL. Мне нравится хранить исходный код моих ядер OpenCL в их собственных файлах, чтобы упростить кодирование и обслуживание (в отличие от встраивания источников напрямую в виде строковых констант в связанный код C ++). Это неизбежно приводит к вопросу о том, как загрузить их в среду выполнения OpenCL, когда придет время распространять двоичные файлы - в идеале, исходный код OpenCL включен в двоичный файл, поэтому двоичный файл не должен находиться в определенном месте. внутри некоторой структуры каталогов, чтобы знать, где находится исходный код OpenCL.
Я хотел бы включить файлы OpenCL в качестве строковых констант где-нибудь, и желательно без использования дополнительных шагов сборки или внешних инструментов (для кросс-компилятора / кросс-компиляции простота использования платформы ... т.е. нет xxd
и т.п.). Я думал, что наткнулся на метод, основанный на втором ответе в этой ветке, например:
#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 ++ без вызова внешних инструментов или загрязнения файлов посторонним кодом. Идеи?
РЕДАКТИРОВАТЬ : Как указал Potatoswatter, поведение вышеупомянутого не определено, поэтому метод препроцессора по-настоящему кросс-компилятора, который не включает касание файлов, которые необходимо преобразовать в строку, вероятно, невозможен (Первый человек, обнаруживший чудовищный взлом, который действительно работает для большинства / всех компиляторов, получает очки ответа). Для любопытных я закончил тем, что было предложено во втором ответе здесь ... то есть я добавил макрос STRINGIFY
непосредственно в файлы OpenCL, которые я включал:
В somefile.cl
:
STRINGIFY(
... // Lots of OpenCL code
)
В 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.