Remarque : cette question n'a rien à voir avec OpenCL en soi... consultez le dernier paragraphe pour un exposé succinct de ma question. Mais pour fournir un peu de contexte :
Je suis en train d'écrire un code C++ qui utilise OpenCL. J'aime garder les sources de mes noyaux OpenCL dans leurs propres fichiers, afin de faciliter le codage et la maintenance (par opposition à l'intégration des sources directement en tant que constantes de chaîne dans le code C++ associé). Cela conduit inévitablement à la question de savoir comment les charger dans le runtime OpenCL une fois que le moment est venu de distribuer les binaires---idéalement, la source OpenCL est incluse dans le binaire, de sorte que le binaire n'a pas besoin d'être à un endroit spécifique dans une structure de répertoire pour savoir où se trouve le code source OpenCL.
J'aimerais inclure les fichiers OpenCL en tant que constantes de chaîne quelque part, et de préférence sans utiliser d'étapes de compilation supplémentaires ou d'outils externes (pour une facilité d'utilisation entre compilateurs et plates-formes... c'est-à-dire, pas de xxd
et autres). J'ai pensé être tombé sur une technique basée sur la deuxième réponse dans ce fil, comme ça :
#define STRINGIFY(src) #src
inline const char* Kernels() {
static const char* kernels = STRINGIFY(
#include "kernels/util.cl"
#include "kernels/basic.cl"
);
return kernels;
}
Notez que je préférerais ne pas intégrer l'élément STRINGIFY
dans mon code OpenCL si cela est possible (comme cela a été fait dans la question SO référencée ci-dessus). Maintenant, cela fonctionne à merveille avec le compilateur Clang/LLVM, mais GCC meurt d'une mort horrible ("Unterminated argument list invoking macro STRINGIFY" et diverses "erreurs" de syntaxe liées au contenu des fichiers .cl apparaissent). Donc, il est clair que cette technique exacte n'est pas utilisable par tous les compilateurs (je n'ai pas essayé MSVC, mais j'aimerais qu'elle fonctionne là aussi)... Comment pourrais-je la masser un minimum pour qu'elle fonctionne sur tous les compilateurs ?
En résumé, j'aimerais disposer d'une technique conforme aux normes pour inclure le contenu d'un fichier en tant que constante de chaîne C/C++ sans faire appel à des outils externes ou polluer les fichiers avec du code étranger. Des idées ?
EDITAR : Comme Potatoswatter l'a fait remarquer, le comportement de ce qui précède n'est pas défini, donc une technique de préprocesseur vraiment inter-compilateur qui n'implique pas de toucher aux fichiers-à-stringifier n'est probablement pas possible (la première personne à comprendre un hack odieux qui fait fonctionne pour la plupart/toutes les compilations obtient les points de réponse). Pour les curieux, j'ai fini par faire ce qui était suggéré dans la deuxième réponse ici ... c'est-à-dire que j'ai ajouté le STRINGIFY
directement aux fichiers OpenCL que j'incluais :
En somefile.cl
:
STRINGIFY(
... // Lots of OpenCL code
)
En somefile.cpp
:
#define STRINGIFY(src) #src
inline const char* Kernels() {
static const char* kernels =
#include "somefile.cl"
;
return kernels;
}
Cela fonctionne dans les compilateurs dans lesquels je l'ai essayé (Clang et GCC également, puisqu'il n'y a pas de directives de préprocesseur à l'intérieur de la macro), et n'est pas une charge trop importante, du moins dans mon contexte (c'est-à-dire que cela n'interfère pas avec la coloration syntaxique/l'édition des fichiers OpenCL). Une caractéristique des approches de préprocesseur comme celle-ci est que, puisque les chaînes adjacentes sont concaténées, vous pouvez écrire
inline const char* Kernels() {
static const char* kernels =
#include "utility_functions.cl"
#include "somefile.cl"
;
return kernels;
}
et tant que la macro STRINGIFY est dans les deux .cl
les chaînes sont concaténées, ce qui vous permet de modulariser votre code OpenCL.