Módulos de C++ y el ABI de C++


He estado leyendo sobre la propuesta de módulos C++ ( último borrador) pero no entiendo completamente qué problema(s) pretende resolver.

¿Su propósito es permitir que un módulo construido por un compilador sea utilizado por cualquier otro compilador (en el mismo sistema operativo/arquitectura, por supuesto)? Es decir, ¿la propuesta equivale a estandarizar el ABI de C++?

Si no es así, ¿se está considerando otra propuesta que estandarice la ABI de C++ y permita a los compiladores interoperar?

Author: Rapptz, 2012-01-31

3 answers

Los encabezados precompilados (PCH) son archivos especiales que ciertos compiladores pueden generar para a .archivo cpp. Lo que son es exactamente eso: código fuente pre-compilado. Son código fuente que ha sido alimentado a través del compilador y construido en un formato dependiente del compilador.

Los PCH se usan comúnmente para acelerar la compilación. Usted pone encabezados de uso común en el PCH, a continuación, sólo incluir el PCH. Cuando haces un #include en el PCH, tu compilador no hace el trabajo #include habitual. En su lugar carga estos símbolos precompilados directamente en el compilador. No se ejecuta un preprocesador de C++. No se ejecuta un compilador de C++. No # incluyendo un millón de archivos diferentes. Se carga un archivo y los símbolos aparecen completamente formados directamente en el espacio de trabajo del compilador.

Menciono todo eso porque los módulos son PCHs en su forma perfecta. Los PCHS son básicamente un hack gigante construido sobre un sistema que no permite módulos reales. El propósito de los módulos es, en última instancia, ser capaz de tomar una generar un archivo de módulo específico del compilador que contenga símbolos, y luego algún otro archivo carga ese módulo según sea necesario. Los símbolos están pre-compilados, así que de nuevo, no hay necesidad de #incluir un montón de cosas, ejecutar un compilador, etc. El código dice: import thing.foo, y aparece.

Mire cualquiera de las cabeceras de biblioteca estándar derivadas de STL. Tomemos <map> por ejemplo. Las probabilidades son buenas de que este archivo sea gigantesco o tenga muchas #inclusiones de otros archivos que hagan que el archivo resultante sea gigantesco. Eso es un montón de análisis de C++ que tiene que suceder. Debe suceder para cada .archivo cpp que tiene #include <map> en él. Cada vez que compila un archivo fuente, el compilador tiene que recompilar lo mismo. Sobre. Y cambio. Y otra vez.

¿Cambia <map> entre compilaciones? No, pero tu compilador no puede saberlo. Así que tiene que seguir recompilándolo. Cada vez que tocas una .archivo cpp, debe compilar cada cabecera que este .archivo cpp incluye. Aunque no hayas tocado esos encabezados o archivos de origen que afectan a esos encabezados.

Los archivos PCH eran una forma de solucionar este problema. Pero son limitados, porque son solo un truco. Solo se puede incluir uno por .archivo cpp, porque debe ser la primera cosa incluida por .archivos cpp. Y como solo hay un PCH, si haces algo que cambie el PCH (como agregarle una nueva cabecera), tienes que recompilar todo en ese PCH.

Los módulos no tienen esencialmente nada que ver con el compilador cruzado ABI (aunque tener uno de esos sería bueno, y los módulos harían un poco más fácil definir uno). Su propósito fundamental es acelerar los tiempos de compilación.

 33
Author: Nicol Bolas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-31 00:44:27

Los módulos son lo que ofrecen Java, C# y muchos otros lenguajes modernos. Reducen enormemente el tiempo de compilación simplemente porque el código que está en la cabecera de hoy no tiene que ser analizado una y otra vez, cada vez que se incluye. Cuando dices #include <vector>, el contenido de <vector> se copiará en el archivo actual. #include realmente no es nada más que copiar y pegar.

En el mundo del módulo, simplemente dice import std.vector; por ejemplo y el compilador carga la tabla query/symbol de ese módulo. El el archivo de módulo tiene un formato que hace que sea fácil para el compilador analizarlo y usarlo. También solo se analiza una vez, cuando se compila el módulo. Después de eso, el archivo de módulo generado por el compilador solo se consulta para obtener la información que se necesita.

Debido a que los archivos de módulo son generados por el compilador, estarán muy estrechamente vinculados a la representación interna del compilador del código C++ (AST) y, como tal, lo más probable es que no sean portátiles (al igual que el .o/.so/.a archivos, porque del nombre que destroza etc.).

 12
Author: Xeo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-31 00:20:08

Los módulos en C++ tienen que ser principalmente mejores que las soluciones actuales, es decir, cuando una biblioteca consta de un archivo *.so y *.archivo h con API. Tienen que resolver los problemas que hay hoy con # includes, es decir:

  • require macroguards (macros que impiden que las definiciones se proporcionen varias veces)
  • están estrictamente basados en texto (por lo que pueden ser engañados y en condiciones normales se reinterpretan, lo que también da la oportunidad de verse de manera diferente en diferentes compilation unit to be next linked together)
  • no distingue entre bibliotecas dependientes que solo se utilizan instrumentalmente y que se derivan de (especialmente si el encabezado proporciona plantillas de función en línea)

A pesar de lo que dice Xeo, los módulos no existen en Java o C#. De hecho, en estos lenguajes " loading modules "se basa en que"ok, aquí tienes el CLASSPATH y busca a través de él para encontrar los módulos que puedan proporcionar símbolos que el archivo fuente realmente utiliza". El la declaración "import" en Java no es " module request "en absoluto - lo mismo que" using"en C++ ("import ns.ns2.* "in Java is the same as " using namespace ns:: ns2" in C++). No creo que esta solución pueda ser usada en C++. La aproximación más cercana que puedo imaginar son paquetes en Vala o módulos en Tcl (los de la versión 8.5).

Me imagino que los módulos C++ no son más bien posibles para ser multiplataforma, ni cargado dinámicamente (requiere un cargador de módulo dinámico C++ dedicado - no es imposible, pero hoy es difícil de definir). Definitivamente dependerán de la plataforma y también deben configurarse cuando se solicite. Pero un ABI de C++ estable prácticamente solo se requiere dentro del rango de un sistema, al igual que lo es con C++ ABI ahora.

 8
Author: Ethouris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-20 20:28:28