Подтвердить что ты не робот

Зачем сначала компилировать файл объекта?

В прошлом году я начал программировать в Фортране, работая в исследовательском университете. Большая часть моего предыдущего опыта заключается в веб-языках, таких как PHP или старый ASP, поэтому я новичок для компиляции операторов.

У меня есть два разных кода, которые я изменяю.

Один имеет оператор , создающий файлы .o из модулей (например, gfortran -c filea.f90) перед созданием исполняемого файла.

Другие создают исполняемый файл напрямую (иногда создавая файлы .mod, но не файлы .o, например gfortran -o исполняемый файл filea.f90 fileb.f90. f90).

  • Есть ли причина (кроме, может быть, Make файлов), что один метод предпочтительнее другого?
4b9b3361

Ответ 1

Компиляция в объектные файлы - это то, что называется отдельной компиляцией. Есть много преимуществ и несколько недостатков.

Преимущества:

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

Недостатки:

  • Есть некоторые оптимизации (например, оптимизирующие функции), которые компилятор не может выполнить, и компоновщику все равно; однако многие компиляторы теперь включают в себя возможность выполнять "оптимизацию времени соединения", что в значительной степени отрицает этот недостаток. Но это все еще проблема для системных библиотек и сторонних библиотек, особенно для разделяемых библиотек (невозможно оптимизировать части компонентов, которые могут меняться при каждом запуске, однако другие методы, такие как компиляция JIT, могут смягчить это).
  • в некоторых языках программист объектного файла должен предоставить какой-то заголовок для использования других, которые свяжутся с этим объектом. (т.е. в C вам необходимо предоставить файлы .h). Но в любом случае это хорошая практика.
  • на языках с текстовым включением, например, C или С++, если вы измените прототип файла, вы должны изменить его в двух местах. Однажды в файле заголовка, один раз в файле реализации (если вы используете С++, вы также можете встроить реализацию функции в заголовок, но тогда он больше не отделяет компиляцию).

Ответ 2

Если у вас есть проект с несколькими 100 исходными файлами, вы не хотите перекомпилировать все из них каждый раз, когда он изменяется. Компилируя каждый исходный файл в отдельный объектный файл и только перекомпилируйте те исходные файлы, на которые влияет изменение, вы тратите минимальное время на изменение исходного кода на новый исполняемый файл.

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

Ответ 3

Файл .o - это файл объекта. Это промежуточное представление конечной программы.

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

Одна из вещей, которые требуется программе, прежде чем она может быть запущена, похожа на образ памяти.

Например.

Если у вас есть ваша основная программа, и она вызывает обычную A. (Это искусственный fortran, я не трогал десятилетия, поэтому работайте со мной здесь.)

PROGRAM MAIN
INTEGER X,Y
X = 10
Y = SQUARE(X)
WRITE(*,*) Y
END

Затем у вас есть функция SQUARE.

FUNCTION SQUARE(N)
SQUARE = N * N
END

Индивидуально скомпилированные единицы. Вы можете видеть, чем когда скомпилирована MAIN, она не ЗНАЕТ, где находится "ПЛОЩАДЬ", на каком адресе она находится. Он должен знать, что при вызове команды JUMP SUBROUTINE (JSR) микропроцессора инструкция имеет куда-то пойти.

Файл .o уже имеет инструкцию JSR, но он не имеет фактического значения. Это происходит позже на этапе компоновки или загрузки (в зависимости от вашего приложения).

Итак, MAINS.o файл имеет весь код для основного и список ссылок, которые он хочет разрешить (в частности, SQUARE). ПЛОЩАДЬ в основном автономна, у нее нет ссылок, но в то же время у нее не было адреса о том, где она существует в памяти.

Линкером будет удаляться все файлы .o и объединить их в один exe. В старые времена скомпилированный код в буквальном смысле был бы образ памяти. Программа запускается с некоторого адреса и просто загружается в оперативную память, а затем выполняется. Таким образом, в сценарии вы можете увидеть компоновщик, берущий два файла .o, объединив их вместе (чтобы получить фактический адрес SQUARE), затем он вернется и найдет ссылку SQUARE в MAIN и заполнит адрес.

Современные линкеры не идут так далеко и откладывают большую часть этой окончательной обработки до того, когда программа загружена. Но концепция похожа.

Скомпилировав файлы .o, вы получите многократно используемые единицы логики, которые затем объединены позже процессами связывания и загрузки перед выполнением.

Другим приятным аспектом является то, что файлы .o могут поступать с разных языков. Пока механизмы вызова совместимы (т.е. Как передаются аргументы и из функций и процедур), то после компиляции в .o исходный язык становится менее актуальным. Вы можете связать, объединить, код C с кодом FORTRAN, скажем.

В PHP et all процесс отличается от того, что весь код загружается в одно изображение во время выполнения. Вы можете рассматривать файлы FORTRAN.o, похожие на то, как вы будете использовать PHP, включают механизм объединения файлов в большое сплоченное целое.

Ответ 4

Другая причина, кроме времени компиляции, заключается в том, что процесс компиляции представляет собой многошаговый процесс .

The multi-part process.

Объектные файлы - это всего лишь один промежуточный результат этого процесса. В конечном итоге они будут использованы компоновщиком для создания исполняемого файла.

Ответ 5

Мы собираем объектные файлы, чтобы иметь возможность связывать их вместе, чтобы сформировать более крупные исполняемые файлы. Это не единственный способ сделать это.

Есть также компиляторы, которые этого не делают, но вместо этого компилируются в память и сразу же выполняют результат. Раньше, когда ученикам приходилось использовать мэйнфреймы, это было стандартным. Turbo Pascal также сделал это таким образом.