Вопросы по компилятору и компоновщику GCC - PullRequest
2 голосов
/ 08 декабря 2011

Допустим, ваша программа состоит из двух исходных файлов (main.c и Additional.c) и двух заголовочных файлов (Declarations.h и Additional.h).

Затем вы запускаете компилятор следующим образом:

$gcc main.c auxiliary.c -o myprogram

Вопрос 1 : Будет ли компилятор создавать один единственный объектный файл для моей программы (т. Е. Отсутствуют только библиотеки) или он создаст два объектных файла, по одному для каждого исходного файла (а затем скомпонует все вместе)

Вопрос 2 : есть ли необходимость вызывать компоновщик отдельно? Потому что, если вы используете команду выше, компилятор позаботится об этом за вас, верно?

Вопрос 3 : Почему некоторые библиотеки связываются автоматически (например, stdio) и почему некоторые требуют дополнительной работы (например, math.h требует добавления -lm при компиляции). Что означает -lm?

Вопрос 4 : Предположим, у вас есть один исходный файл, и ваша программа не нуждается во внешней библиотеке. Значит ли это, что объектный код, который вы получите от компилятора, уже будет исполняемым? (то есть, компилируя его как $ gcc -c main.c).

Ответы [ 3 ]

4 голосов
/ 08 декабря 2011
  1. gcc обычно создает один объект на исходные файлы. Но есть опция -combine, чтобы сказать, что вы хотите иначе.

  2. Перекомпилировать все, когда у вас есть несколько десятков исходных файлов, не очень хорошая идея (когда у вас их больше, вы разбиваете их по библиотекам).

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

  4. Я жду, чтобы увидеть программу, которая не использует какую-либо часть даже стандартной библиотеки (логический вызов main выполняется как exit(main(argc, argv)), поэтому вызывается как минимум exit), а затем код запуска и завершения.

3 голосов
/ 08 декабря 2011
  1. gcc создает один объектный файл на исходный файл, а затем связывает их для создания исполняемого файла.

  2. Ваш пример доказывает, что gcc может связать все необходимые шаги

  3. Библиотека, которая автоматически связывается, является стандартной библиотекой C. Остальные должны быть указаны. Это позволяет создать меньший исполняемый файл, когда вам не нужен atan2().
    -lm указывает компилятору, что он должен найти библиотеку математики, чей идентификатор m. В Unix его имя файла libm.so или libm.a, в зависимости от того, является ли ссылка динамической (выполняется во время выполнения и приводит к уменьшению исполняемого файла) или статической (выполняется во время ссылки и приводит к автономному выполнению). *

  4. Нет. В любом случае он должен быть связан со стандартной библиотекой C. Кроме того, формат файла объектного кода отличается от исполняемого файла.

1 голос
/ 08 декабря 2011

Вопрос 1 : выполните инструкцию gcc с помощью '-save-temps', и вы увидите, что компилятор создает два объектных файла.

Вопрос 2 : Вызов компоновщика неявный.Команда 'gcc' на самом деле не является компилятором, но управляет процессом компиляции, вызывая препроцессор, компилятор, ассемблер и компоновщик по мере необходимости.В небольших программах может быть хорошей идеей позволить gcc позаботиться обо всем, но для более крупных программ со многими исходными файлами это будет означать перекомпиляцию всех исходных файлов, даже если они не изменились.

Вопрос 3 : Это вопрос соглашения.(Библиотека m - это математическая библиотека.)

Вопрос 4 : Нет, дело не в этом.Всегда есть некоторый дополнительный код, который должен быть связан, чтобы заботиться о требованиях запуска / разрыва процесса.В Linux это файлы crt1.o, crti.o, crtbegin.o и crtn.o.

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