Tropatería preprocesador (encadenando un #include)

Nota: Esta pregunta no tiene nada que ver con OpenCL per se ... verifique el último párrafo para obtener una declaración sucinta de mi pregunta. Pero para proporcionar algunos antecedentes:

Estoy escribiendo un código C ++ que hace uso de OpenCL. Me gusta mantener la fuente de mis núcleos OpenCL en sus propios archivos, para facilitar la codificación y el mantenimiento (en lugar de incrustar las fuentes directamente como constantes de cadena en el código C ++ asociado). Esto inevitablemente lleva a la pregunta de cómo cargarlos en el tiempo de ejecución de OpenCL una vez que llega el momento de distribuir binarios, idealmente, la fuente de OpenCL está incluida en el binario, de modo que el binario no necesita estar en un lugar específico dentro de alguna estructura de directorio para saber dónde está el código fuente de OpenCL.

Me gustaría incluir los archivos OpenCL como constantes de cadena en alguna parte, y preferiblemente sin el uso de pasos de compilación adicionales o herramientas externas (para la facilidad de uso entre compiladores / plataformas cruzadas ... es decir, no axxd y similares). Pensé que había tropezado con una técnica basada en la segunda respuesta enest hilo, así:

#define STRINGIFY(src) #src

inline const char* Kernels() {
  static const char* kernels = STRINGIFY(
    #include "kernels/util.cl"
    #include "kernels/basic.cl"
  );
  return kernels;
}

Nota que preferiría no incrustar laSTRINGIFY macro en mi código OpenCL si es posible (como se hizo en la pregunta SO mencionada anteriormente). Ahora, esto funciona maravillosamente en el compilador Clang / LLVM, pero GCC muere de una muerte horrible (aparece "Lista de argumentos no invocados que invoca macro STRINGIFY" y aparecen varios "errores" de sintaxis relacionados con el contenido de los archivos .cl). Entonces, claramente esta técnica exacta no se puede usar en los compiladores (no he probado MSVC, pero me gustaría que funcione allí también) ... ¿Cómo podría masajearla mínimamente para que funcione en los compiladores?

En resumen, me gustaría una técnica que cumpla con los estándares para incluir el contenido de un archivo como una constante de cadena C / C ++ sin invocar herramientas externas o contaminar los archivos con código extraño. Ideas?

EDITA: Como señaló Potatoswatter, el comportamiento de lo anterior no está definido, por lo que una verdadera técnica de preprocesador de compilación cruzada que no implique tocar los archivos para ser encadenados probablemente no sea posible (la primera persona en descubrir un atroz piratear quehac work para la mayoría / todos los compiladores obtienen los puntos de respuesta). Para los curiosos, terminé haciendo lo que se sugirió en la segunda respuestaaqu ... es decir, agregué laSTRINGIFY macro directamente a los archivos OpenCL que estaba incluyendo:

Insomefile.cl:

STRINGIFY(
  ... // Lots of OpenCL code
)

Insomefile.cpp:

#define STRINGIFY(src) #src

inline const char* Kernels() {
  static const char* kernels =
    #include "somefile.cl"
    ;
  return kernels;
}

Esto funciona en los compiladores en los que lo he probado (Clang y GCC también, ya que no tiene directivas de preprocesador dentro de la macro), y no es una carga demasiado grande al menos en mi contexto (es decir, no no interfiera con la sintaxis resaltando / editando los archivos OpenCL). Una característica de los enfoques de preprocesador como este es que, dado que las cadenas adyacentes se concatenan, puede escribir

inline const char* Kernels() {
  static const char* kernels =
    #include "utility_functions.cl"
    #include "somefile.cl"
    ;
  return kernels;
}

y siempre que la macro STRINGIFY esté en ambos.cl archivos, las cadenas se concatenan, lo que le permite modularizar su código OpenCL.

Respuestas a la pregunta(4)

Su respuesta a la pregunta