Preprocessor tomfoolery (restringindo um #include)
Nota: Esta questão não tem nada a ver com o OpenCL em si ... verifique o último parágrafo para obter uma declaração sucinta da minha pergunta. Mas, para fornecer alguns antecedentes:
Estou escrevendo algum código C ++ que utiliza o OpenCL. Eu gosto de manter a fonte dos meus kernels OpenCL em seus próprios arquivos, para facilitar a codificação e a manutenção (em vez de incorporar as fontes diretamente como constantes de string no código C ++ associado). Isso inevitavelmente leva à questão de como carregá-los no tempo de execução do OpenCL quando chegar a hora de distribuir os binários --- idealmente, a fonte do OpenCL é incluída no binário, para que o binário não precise estar em um local específico em alguma estrutura de diretório para saber onde está o código-fonte do OpenC
Gostaria de incluir os arquivos OpenCL como constantes de string em algum lugar e, de preferência, sem o uso de etapas adicionais de compilação ou ferramentas externas (para facilidade de uso entre compiladores / plataformas) ... ou seja, não paraxxd
e similar). Eu pensei que tinha tropeçado em uma técnica baseada na segunda resposta emist thread, assim:
#define STRINGIFY(src) #src
inline const char* Kernels() {
static const char* kernels = STRINGIFY(
#include "kernels/util.cl"
#include "kernels/basic.cl"
);
return kernels;
}
Observe que eu preferiria não incorporar oSTRINGIFY
macro no meu código OpenCL, se possível (como foi feito na pergunta SO mencionada acima). Agora, isso funciona maravilhosamente no compilador Clang / LLVM, mas o GCC sofre uma morte horrível ("Lista de argumentos não terminada invocando a macro STRINGIFY" e vários "erros" de sintaxe relacionados ao conteúdo dos arquivos .cl são exibidos). Então, claramente, essa técnica exata não é utilizável em compiladores (ainda não tentei o MSVC, mas também gostaria que funcionasse lá) ... Como eu poderia massageá-lo minimamente para que ele funcionasse em compiladores?
Em resumo, eu gostaria de uma técnica compatível com os padrões para incluir o conteúdo de um arquivo como uma constante de string C / C ++ sem chamar ferramentas externas ou poluir os arquivos com código estranho. Ideias?
EDITA: Como apontou Potatoswatter, o comportamento acima é indefinido; portanto, uma técnica de pré-processador verdadeiramente compilador cruzado que não envolve o toque nos arquivos a serem especificados, provavelmente não é possível (a primeira pessoa a descobrir um hediondo hackear issofa work para a maioria / todos os compiladores obtém os pontos de resposta). Para os curiosos, acabei fazendo o que foi sugerido na segunda respostaAqu ... isto é, adicionei oSTRINGIFY
macro diretamente para os arquivos OpenCL que eu estava incluindo:
Emsomefile.cl
:
STRINGIFY(
... // Lots of OpenCL code
)
Emsomefile.cpp
:
#define STRINGIFY(src) #src
inline const char* Kernels() {
static const char* kernels =
#include "somefile.cl"
;
return kernels;
}
Isso funciona nos compiladores em que eu experimentei (Clang e GCC também, já que não possui diretivas de pré-processador dentro da macro) e não é um fardo muito grande, pelo menos no meu contexto (ou seja, não interfere com a sintaxe destacando / editando os arquivos OpenCL). Um recurso das abordagens de pré-processador como este é que, como as seqüências adjacentes são concatenadas, você pode escrever
inline const char* Kernels() {
static const char* kernels =
#include "utility_functions.cl"
#include "somefile.cl"
;
return kernels;
}
e contanto que a macro STRINGIFY esteja em ambos.cl
, as strings são concatenadas, permitindo modularizar seu código OpenC