#c #compiler-construction #linker #object-files
#c #компилятор-конструкция #компоновщик #объектные файлы
Вопрос:
Почему скомпилированные языки программирования (например, C ) настроены на создание множества объектных файлов, которые связаны друг с другом, а не на создание одного большого объекта?
Например (написанный на C , может применяться к любому скомпилированному языку), рассмотрим два файла в проекте main.cpp
и auxiliary.cpp
. В чем разница между main.cpp
и auxiliary.cpp
, который компилируется в main.o
и auxiliary.o
, а затем связывается с main.exe
, и main.cpp
с #include auxiliary.cpp
тем, который компилируется только main.o
и связан с main.exe
? Насколько мне известно, это, по крайней мере, на первый взгляд, дало бы тот же результат.
Я вижу необходимость в нескольких объектах в случае многоязычных проектов, но не иначе. Несколько объектов каким-то образом дают компоновщику больше гибкости при создании исполняемого файла?
Комментарии:
1. Как бы вы нашли что-нибудь в одном cpp-файле длиной в несколько сотен тысяч строк, содержащем тысячи классов? Также, когда я меняю 1 строку, я бы не хотел ждать 1 час для компиляции.
2. При использовании команды
#include
препроцессора исходный код будет отображаться во многих файлах для пользователя, но для компилятора будет отображаться как один файл.3. Это приведет к излишне долгому времени компиляции.
Ответ №1:
Отдельные модули компиляции, подобные этому, ускоряют компиляцию. Если вы вносите изменения auxilliary.cpp
, компилятору нужно только воссоздать auxilliary.o
, а не перекомпилировать все. Это становится особенно важным, чем больше проект.
Ответ №2:
Я могу ответить на это риторическим вопросом: почему вы пишете много функций вместо одной большой?
Та же логика применяется на уровне ссылок.
Ответ №3:
Если вам нужен один большой двоичный файл, вам просто нужно создать статическую библиотеку, но это не объектный код из одной единицы перевода, а из многих.
Теперь подумайте, действительно ли то, что вы просите, имеет смысл: если бы требовалось создать один файл .o, ему пришлось бы объединять результаты компиляции каждого cpp в этот двоичный файл по мере его сборки, эффективно оплачивая стоимость многократного связывания. Кроме того, изменение одной единицы преобразования потребует, чтобы компилятор выяснил, какие из символов в большом объектном файле взяты из исходной версии этой единицы преобразования, удалил их из объекта и добавил новые после перестройки.