Модули C ++ и ABI C ++ - PullRequest
       37

Модули C ++ и ABI C ++

24 голосов
/ 31 января 2012

Я читал о предложении модулей C ++ ( последний черновик ), но я не до конца понимаю, какие проблемы он / она стремится решить.

Является ли его цельюразрешить использовать модуль, созданный одним компилятором, любым другим компилятором (конечно, в той же ОС / архитектуре)?То есть, составляет ли предложение стандартизацию ABI C ++?

Если нет, рассматривается ли другое предложение, которое стандартизирует ABI C ++ и позволит компиляторам взаимодействовать?

Ответы [ 3 ]

33 голосов
/ 31 января 2012

Предварительно скомпилированные заголовки (PCH) - это специальные файлы, которые определенные компиляторы могут генерировать для файла .cpp.Это то, что они представляют собой: предварительно скомпилированный исходный кодЭто исходный код, который был передан через компилятор и встроен в формат, зависящий от компилятора.

PCH обычно используются для ускорения компиляции.Вы помещаете обычно используемые заголовки в PCH, а затем просто включаете PCH.Когда вы делаете #include на PCH, ваш компилятор на самом деле не выполняет обычную работу #include.Вместо этого он загружает эти предварительно скомпилированные символы прямо в компилятор.Нет запуска препроцессора C ++.Нет запуска компилятора C ++.Нет, включая миллион разных файлов.Один файл загружен, и символы кажутся полностью сформированными непосредственно в рабочей области вашего компилятора.

Я упоминаю все это, потому что модули являются PCHs в их perfect форме.PCH - это, по сути, гигантский хак, построенный поверх системы, которая не учитывает фактические модули.В конечном счете, целью модулей является получение файла, создание файла модуля для конкретного компилятора, который содержит символы, а затем некоторые другие файлы загружают этот модуль по мере необходимости.Символы предварительно скомпилированы, поэтому, опять же, нет необходимости #include кучу вещей, запустить компилятор и т. Д. Ваш код говорит, import thing.foo, и он появляется.

Посмотрите на любой изполученные из STL заголовки стандартной библиотеки.Возьмите <map> для примера.Хорошие шансы, что этот файл либо гигантский, либо содержит много # включений других файлов, которые делают результирующий файл гигантским.Это много синтаксического анализа C ++, который должен произойти.Это должно произойти для каждого .cpp файла, содержащего #include <map>.Каждый раз, когда вы компилируете исходный файл, компилятор должен перекомпилировать одно и то же.Над.И более.И снова.

Меняется ли <map> между компиляциями?Нет, но ваш компилятор не может этого знать.Так что он должен продолжать перекомпилировать его.Каждый раз, когда вы прикасаетесь к файлу .cpp, он должен компилировать каждый заголовок, который содержит этот файл .cpp.Даже если вы не касались тех заголовков или исходных файлов, которые влияют на эти заголовки.

PCH-файлы были способом обойти эту проблему.Но они ограничены, потому что они просто взломать.Вы можете включить только один файл .cpp, потому что он должен быть первым, включенным в файлы .cpp.И поскольку существует только один PCH, если вы делаете что-то, что изменяет PCH (например, добавляете к нему новый заголовок), вам нужно перекомпилировать все в этом PCH.

Модули по существуне имеет ничего общего с кросс-компилятором ABI (хотя было бы неплохо иметь один из них, а с модулями было бы немного легче его определить).Их основная цель - ускорить время компиляции.

12 голосов
/ 31 января 2012

Модули - это то, что Java, C # и многие другие современные языки предлагают.Они значительно сокращают время компиляции просто потому, что код, который находится в сегодняшнем заголовке, не нужно анализировать снова и снова, каждый раз, когда он включается.Когда вы говорите #include <vector>, содержимое <vector> будет скопировано в текущий файл.#include на самом деле - не что иное, как копирование и вставка.

В мире модулей вы просто говорите, например, import std.vector;, и компилятор загружает таблицу запросов / символов этого модуля.Файл модуля имеет формат, облегчающий его анализ и использование компилятором.Он также анализируется только один раз , когда модуль компилируется.После этого генерируемый компилятором файл модуля просто запрашивается для получения необходимой информации.

Поскольку файлы модуля генерируются компилятором, они будут довольно тесно связаны с внутренним представлением компилятора кода C ++ (AST) и, скорее всего, не будет переносимым (как современные файлы .o / .so / .a из-за искажения имени и т. Д.).

8 голосов
/ 21 июля 2012

Модули в C ++ должны быть в первую очередь лучше, чем современные решения, то есть когда библиотека состоит из файла * .so и * .h с API.Они должны решить проблемы, которые сегодня существуют с #include, то есть:

  • требуют макрогвардейцев (макросы, которые предотвращают предоставление определений несколько раз)
  • строго текстовые (поэтому они могут быть обмануты и в нормальных условиях переосмыслены, что также дает возможность выглядеть по-разному в другом модуле компиляции для последующего связывания друг с другом)
  • не делает различий между зависимыми библиотеками, которые используются только в качестве инструмента и полученыfrom (особенно если заголовок содержит шаблоны встроенных функций)

Несмотря на то, что говорит Xeo, модули не существуют в Java или C #.Фактически, в этих языках «загрузка модулей» основана на том, что «хорошо, здесь у вас есть CLASSPATH и выполните поиск по нему, чтобы найти любые модули, которые могут предоставлять символы, которые фактически использует исходный файл».Объявление «import» в Java вообще не является «запросом модуля» - то же самое, что и «using» в C ++ («import ns.ns2. *» В Java - то же самое, что «using пространство имен ns :: ns2» в C ++),Я не думаю, что такое решение может быть использовано в C ++.Самое близкое приближение, которое я могу себе представить, - это пакеты в Vala или модули в Tcl (версии 8.5).

Я полагаю, что модули C ++ не могут быть кроссплатформенными или динамически загруженными (требуется специальный C ++).динамический модуль загрузки - это не невозможно, но сегодня сложно определить).Они определенно будут зависеть от платформы и должны быть настраиваемыми по запросу.Но стабильный C ++ ABI практически необходим только в пределах одной системы, так же как и сейчас с C ++ ABI.

...