2012-01-31 17 views
23

He estado leyendo acerca de la propuesta de módulos C++ (latest draft) pero no entiendo completamente qué problema (s) intenta resolver.C++ Modules y C++ ABI

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

En caso negativo, ¿se está considerando otra propuesta que normalice el ABI de C++ y permita que los compiladores interactúen?

Respuesta

31

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

PCH se utilizan comúnmente para acelerar la compilación. Coloca los encabezados comúnmente utilizados en el PCH, luego simplemente incluya el PCH. Cuando haces un #include en el PCH, tu compilador no hace el trabajo habitual de #include. En su lugar, carga estos símbolos precompilados directamente en el compilador. No se ejecuta un preprocesador C++. No ejecuta un compilador de C++. No #incluye un millón de archivos diferentes. Se carga un archivo y los símbolos aparecen completamente formados directamente en el espacio de trabajo de su compilador.

Menciono todo eso porque los módulos son PCH en su forma perfecta. Los PCH son básicamente un truco gigante construido sobre un sistema que no permite módulos reales. El propósito de los módulos es, en última instancia, poder tomar un archivo, generar un archivo de módulo específico del compilador que contenga símbolos y, a continuación, otro archivo carga ese módulo según sea necesario. Los símbolos están precompilados, así que de nuevo, no es necesario #incluir un montón de cosas, ejecutar un compilador, etc. Su código dice, import thing.foo, y aparece.

Mire cualquiera de los encabezados de biblioteca estándar derivados de STL. Tome <map> por ejemplo. Las probabilidades son buenas de que este archivo sea gigantesco o tenga una gran cantidad de #inclusiones de otros archivos que hacen que el archivo resultante sea gigantesco. Eso es mucho análisis de C++ que tiene que suceder. Debe ocurrir para cada archivo .cpp que tiene #include <map> en él. Cada vez que compila un archivo fuente, el compilador tiene que volver a compilar lo mismo. Encima. Y más. Y otra vez.

¿Cambia el <map> entre compilaciones? No, pero tu compilador no puede saber eso. Entonces tiene que seguir compilando.Cada vez que toca un archivo .cpp, debe compilar cada encabezado que este archivo .cpp incluye. Aunque no tocó esos encabezados o archivos fuente que afectan esos encabezados.

Los archivos PCH fueron una forma de evitar este problema. Pero son limitados, porque solo son un truco. Solo puede incluir uno por archivo .cpp, porque debe ser lo primero que incluyan los archivos .cpp. Y dado que solo hay un PCH, si hace algo que cambie el PCH (como agregarle un nuevo encabezado), debe recompilar todo en ese PCH.

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

+1

El propósito fundamental va más allá de acelerar los tiempos de compilación .....: D –

10

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

En el mundo de los módulos, simplemente diga import std.vector; por ejemplo y el compilador carga la tabla de consulta/símbolo de ese módulo. El archivo del 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, solo se consulta el archivo del módulo generado por el compilador para obtener la información necesaria.

Dado que los archivos del módulo son generado por el compilador, van a estar muy estrechamente ligada a la representación interna del compilador del código C++ (AST) y tendrá como tal, es probable que no sea portátil (al igual que .o/.so/.a archivos de hoy , debido a la manipulación de nombres, etc.).

7

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 un archivo * .h con API. Ellos tienen que resolver los problemas que se encuentran hoy con #includes, es decir:

  • requieren macroguards (macros que impiden que las definiciones se proporcionan múltiples veces)
  • son estrictamente basado en texto (para que puedan ser engañados y en condiciones normales, se reinterpretan, lo que da la posibilidad de ver de forma diferente en una unidad de compilación diferente para unirlos a continuación)
  • no distingue entre bibliotecas dependientes que solo se utilizan instrumentalmente y se derivan de (especialmente si el encabezado proporciona una función en línea plantillas)

A pesar de lo que dice Xeo, los módulos no existen en Java o C#. De hecho, en estos lenguajes, "cargar módulos" se basa en ese "ok, aquí tienes el CLASSPATH y busca a través de él para encontrar los módulos que pueden proporcionar símbolos que el archivo fuente realmente usa". La declaración de "importación" en Java no es "solicitud de módulo" en absoluto, igual que "usar" en C++ ("importar ns.ns2. *" En Java es lo mismo que "usar namespace ns :: ns2" en C++) . No creo que esa solución se pueda usar 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).

Imagino que los módulos C++ son más bien imposibles de ser multiplataforma, ni cargados dinámicamente (requiere un cargador de módulos dinámico C++ dedicado, no es imposible, pero hoy es difícil de definir). Definitivamente dependerán de la plataforma y también deberían ser configurables cuando se solicite. Pero un C++ ABI estable es prácticamente solo requerido dentro del rango de un sistema, tal como lo es ahora con C++ ABI.