Как языки, такие как C # и Java, избегают C / C ++ - подобной независимой компиляции? - PullRequest
6 голосов
/ 28 марта 2009

Для моего класса языков программирования я пишу исследовательскую работу по некоторым статьям некоторых важных людей в истории языкового дизайна. Одна из работ Кора Хоара показалась мне странной, потому что она противоречит методам независимой компиляции, использованным в C, а затем в C ++ еще до того, как C даже стал популярным.

Поскольку это в первую очередь оптимизация для ускорения времени компиляции, что такого в Java и C # позволяет им избежать зависимости от независимой компиляции? Это метод компиляции или есть элементы языка, которые облегчают это? И есть ли другие скомпилированные языки, которые использовали эти методы до них?

Ответы [ 6 ]

5 голосов
/ 29 марта 2009

Краткий ответ: Java и C # не избегают отдельной компиляции; они в полной мере используют его.

В чем они отличаются, так это в том, что они не требуют, чтобы программист записывал пару отдельных файлов заголовка / реализации при написании библиотеки многократного использования. Пользователь записывает определение класса один раз, и компилятор извлекает информацию, эквивалентную «заголовку», из этого единственного определения и включает ее в выходной файл как «метаданные типа». Таким образом, выходной файл (.jar, полный .class файлов на Java или сборка .dll на языках .NET) представляет собой комбинацию двоичных файлов И заголовков в одном пакете.

Затем, когда другой класс скомпилирован и зависит от первого класса, он может просматривать метаданные вместо того, чтобы искать отдельный включаемый файл.

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

В компиляторах C ++ часто пытаются ускорить компиляцию, используя «предварительно скомпилированные заголовки». Метаданные в файлах .NET .dll и .class очень похожи на предварительно скомпилированный заголовок - уже проанализированы и проиндексированы, готовы к быстрому поиску.

В результате в этих современных языках существует один способ выполнения модульности, и он обладает характеристиками прекрасно организованной и оптимизированной вручную модульной системы сборки C ++ - довольно изящно, говоря ASFAC ++ B .

4 голосов
/ 28 марта 2009

IMO, одним из самых важных факторов здесь является то, что и Java, и .NET используют промежуточные языки; это означает, что скомпилированный модуль (jar / assembly) содержит в качестве предварительного условия множество выразительных метаданных о типах, методах и т. д .; это означает, что он уже выложен удобно для проверки ссылок. Время выполнения все равно проверяется, на случай, если вы тянете быстро; -p

Это не очень далеко от MIDL, лежащего в основе COM, хотя там TLB часто является отдельной сущностью.

Если я неправильно понял ваш смысл, пожалуйста, дайте мне знать ...

3 голосов
/ 29 марта 2009

Вы можете считать файл java .class похожим на предварительно скомпилированный заголовочный файл в C / C ++. По сути, файл .class является промежуточной формой, которая нужна компоновщику C / C ++, а также всей информацией, содержащейся в заголовке (у Java просто нет отдельного заголовка).

Сформируйте свой комментарий в другом посте:

"Я в основном имею в виду идею в C / C ++, что каждый исходный файл является своим Индивидуальный сборник. это не так много, кажется, дело в C # или Java. "

В Java (я не могу говорить о C #, но я предполагаю, что это то же самое), каждый исходный файл является своей отдельной единицей компиляции. Я не уверен, почему вы думаете, что это не так ... возможно, у нас есть разные определения модуля компиляции?

2 голосов
/ 28 марта 2009

Объектные файлы, сгенерированные C / C ++, предназначены для чтения только компоновщиком, а не компилятором.

2 голосов
/ 28 марта 2009

Требуется некоторая языковая поддержка (в противном случае компиляторы C / C ++ сделали бы это тоже)

В частности, требуется, чтобы компилятор генерировал автономные модули, которые предоставляют метаданные, на которые другие модули могут ссылаться, чтобы вызывать их.

.NET сборки являются простым примером. Все файлы в проекте скомпилированы вместе, генерируя одну DLL. Эта dll может быть запрошена .NET для определения, какие типы она содержит, так что другие сборки могут вызывать функции, определенные в ней.

И чтобы использовать это, на языке должно быть разрешено ссылаться на другие модули.

В C ++, что определяет границу модуля? Язык указывает, что компилятор рассматривает данные только в своем текущем модуле компиляции (файл .cpp + включенные заголовки). Не существует механизма для указания «я бы хотел вызвать функцию Foo в модуле Bar, даже если у меня нет прототипа или чего-либо еще для него во время компиляции». Единственный механизм для обмена информацией о типах между файлами - с помощью: includes.

Есть предложение добавить систему модулей в C ++, но она не будет в C ++ 0x. В последний раз я видел, что план состоял в том, чтобы рассмотреть его для TR1 после 0x.

(Стоит отметить, что система #include в C / C ++ изначально использовалась, потому что она ускорила бы компиляцию . Еще в 70-х годах она позволяла компилятору обрабатывать код в простой линейной форме. Сканирование. Ему не нужно было строить деревья синтаксиса или другие подобные «расширенные» функции. Сегодня таблицы перевернулись и стали огромным узким местом как с точки зрения удобства использования, так и с точки зрения скорости компиляции.)

1 голос
/ 29 марта 2009

Что касается других языков: IIRC Turbo Pascal имеет «единицы», которые вы можете использовать, не имея никакого исходного кода. Я думаю, что смысл состоит в том, чтобы создать метаданные вместе со скомпилированным кодом, который затем может использоваться компилятором для определения интерфейса с модулем (то есть сигнатуры функций, макет класса и т. Д.)

Одной из проблем в C / C ++, которая не позволяет просто заменить #include некоторым видом #import, также является препроцессор, который может полностью изменить значение / синтаксис и т. Д. Включенных / импортированных модулей. Это было бы очень сложно (если не невозможно) с Java-подобной модульной системой.

...