мета-данные страницы
  •  

Это старая версия документа!


gcc

(https://www.opennet.ru/docs/RUS/gcc/)

_ ## Состав компилятора g++ - cpp — препроцессор - as — ассемблер - g++ — компилятор - ld — линкер _ ## Работа с GCC (https://www.opennet.ru/docs/RUS/gcc/gcc1-2.html) #### Общие опции ```shell -Dname=value # Определить имя name в компилируемой программе, как значение value. Эффект такой же, как наличие строки #define name value в начале программы -o filename # Использовать filename в качестве имени для создаваемого файла -Wall # Вывод сообщений о всех предупреждениях или ошибках, возникающих во время компиляции программы ``` #### Остановка на промежуточной стадии ```shell -E # Остановиться после стадии препроцессирования -S # Остановиться после собственно компиляции -c # Компилировать или ассемблировать исходные файлы, но не линковать ``` Компиляция может включать до четырех стадий: препроцессирование, компиляцию, ассемблирование и линковку (всегда в этом порядке). Первые три стадии применяются к отдельному исходному файлу и заканчиваются получением объектного файла; линковка объединяет все объектные файлы. Для любого имени входного файла суффикс определяет какая компиляция требуется: ```shell file.c # Исходный код на C, который нуждается в препроцессировании. file.i # Исходный код на C, который не нуждается в препроцессировании. file.ii # Исходный код на C++, который не нуждается в препроцессировании. file.m # Исходный код на Objective C. Заметим, что вам необходимо подключить библиотеку 'libobjc.a', чтобы заставить Objective C программу работать. file.h # C заголовочный файл (не для компиляции или линковки). file.cc # \ file.cxx # \ file.cpp # / Исходный код на C++, который нуждается в препроцессировании. file.C # / file.s # Ассемблерный код. file.S # Ассемблерный код, который нуждается в препроцессировании. другие # Объектный файл, который нужно отдать прямо на линковку. Так поступают с любым именем файла с нераспознанным суффиксом. ``` Так же язык можно указать явно: `-x язык` Принимаются следующие языки: `c`; `objective-c` ; `c++` ; `c-header` ; `cpp-output` ; `c++-cpp-output` ; `assembler` ; `assembler-with-cpp` #### Опции, которые управляют оптимизацией ```shell -O0 # Не оптимизировать -O1 # Оптимизировать. Оптимизированная трансляции требует несколько больше времени и несколько больше памяти для больших функций -O2 # Оптимизирует больше. GNU CC выполняет почти все поддерживаемые оптимизации, которые не включают уменьшение времени исполнения за счет увеличения длины кода -O3 # Оптимизирует еще больше. Включает все оптимизации, определяемые -O2, а также включает опцию inline-functions.

# Если вы используете многочисленные -O опции с номерами или без номеров уровня, действительной является последняя такая опция. ```

#### Опции управления зависимостями ```shell -lfoo # Использовать при компоновке динамическую библиотеку foo.so # аналогично для статической библиотеки foo.a -l:foo.so # Аналогично, но через двоеточие можно указать полное имя библиотеки -Llibpath # Добавить к стандартным каталогам поиска библиотек путь libpath -Iincludepath # Добавить к стандартным каталогам поиска заголовочных файлов путь includepath ```

Опция `-I/foo/include` не осуществляет сама инклудивание. Она лишь указывает папку, где нужно искать, поэтому нужен ещё и `#include`. То есть нужен и `-I/foo/include`, и `#include`, одного из них недостаточно.

Линковка. `-L/foo/lib` — это указание папки, где нужно искать бинарные файлы библиотеки, т. е. файлы .so и .a. `-lfoo` — это указание на то, что нужно, собственно, прилинковать эту библиотеку к результирующему бинарнику. Имя библиотеки, указанное в опции `-lfoo`, соединится с папкой, указанной в `-L/foo/lib` и получится `/foo/lib/libfoo` (в начало названия файла вставляется слово «lib»), затем сюда прибавится .so (или .a) и опционально номер версии и получится `/foo/lib/libfoo.so` или, скажем, `/foo/lib/libfoo.so.1`. Это и будет тем именем .so-файла, который будет искаться.

Так же, как и при компиляции (a.o из a.c), нужны обе опции `-L/foo/lib` и `-lfoo`. `-L/foo/lib` указывает, где искать. А `-lfoo` даёт окончательную команду на прилинковку.

Вместо `-lfoo` можно прямо написать целиком путь до файла библиотеки, который нужно слинковать, например, `/foo/lib/libfoo.so.1`. Тогда опция `-L/foo/lib` не нужна. Получится так: `cc -o a a.o /foo/lib/libfoo.so.1` ___ ## Примеры #### Простая компиляция Чтобы скомпилировать исходный код, необходимо компилятору gcc передать в качестве параметра исходный код (файл hello.cpp):

```shell g++ hello.cpp -o prog ```

Дополнительный необязательный параметр `-o prog` указывает, что скомпилированный файл будет называться prog.exe. Если не указать этот параметр, то файл будет называться по умолчанию - a.exe.

#### Отдельная компиляция

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

Пример раздельной компиляции и компоновки:

```shell # Скомпилируем исходные файы в объектные файлы g++ -c main.cpp -o main.o g++ -c funcs.cpp -o funcs.o

# Линкуем объектные файлы вместе, чтобы создать исполняемый файл g++ main.o funcs.o -o my_program ``` #### Создание статической библиотеки Допустим, у нас есть исходники с реализациями функций `first.cpp`, `second.cpp` и заголовочник `libmy.h` с объявлением ф-ий из исходников. Скомпилируем и заархивируем: ```shell # компилируем gcc -c first.cpp -o first.o gcc -c second.cpp -o second.o # архивируем: ar crs libmy.a first.o second.o # проверим: file libmy.a # вывод: libmy.a: current ar archive ``` архиватор ar - утилита «склеивает» несколько файлов в один, не сжимая их содержимое. `-c <filename>`: создать архив, если архив с именем «filename» не существует он будет создан, в противном случае файлы будут добавлены к имеющемуся архиву. `-r`: Pадает режим обновления архива, если в архиве файл с указанным именем уже существует, он будет удален, а новый файл дописан в конец архива. `-s`: Добавляет (обновляет) индекс архива. В данном случае индекс архива это таблица, в которой для каждого определенного в архивируемых файлах символического имени (имени функции или блока данных) сопоставлено соответствующее ему имя объектного файла. Индекс архива необходим для ускорения работы с библиотекой - для того чтобы найти нужное определение, отпадает необходимость просматривать таблицы символов всех файлов архива, можно сразу перейти к файлу, содержащему искомое имя. Просмотреть индекс архива можно с помощью уже знакомой утилиты nm воспользовавшись её опцией `-s`.

Для создания индекса архива существует специальная утилита ranlib. Библиотеку libmy.a можно было сотворить и так: ```shell ar cr libmy.a first.o second.o ranlib libmy.a ``` Впрочем библиотека будет прекрасно работать и без индекса архива. #### Подключение статической библиотеки Допустим, у нас есть файл `main.cpp` , содержащий `#include «libmy.h»`. Соберём (компиляция+линковка) программу: ```shell gcc -Wall -c main.c # компиляция программы gcc -o mainprog main.o -L. -llibmy # линковка программы вместе с архивом с реализациями функций ``` Повторю: `-L/путь/к/каталогу/с/библиотеками` указывает путь к каталогу содержащему подключаемые библиотеки. `-l<name>` имя библиотеки задается как «name» без приставки «lib»

Компиляция либы: ```cpp // компиляция lib.cpp в объектный файл g++ -c lib.cpp -o lib.o // архивируем в статическую библиотеку ar rcs libmylib.a lib.o ``` Использование либы: ```cpp // компилим файл main с подключением либы g++ main.cpp -o prog -L. -lmylib ``` Здесь: - `-L .` указывает компилятору искать библиотеку в текущем каталоге. - `-lmylib` говорит компилятору использовать библиотеку `libmylib.a`. Эти шаги создадут исполняемый файл `prog`, содержащий код из `main.cpp`, а также функции из вашей статической библиотеки `libmylib.a`. Если вы хотите создать динамическую библиотеку, то процесс будет немного отличаться. Для этого вместо создания статической библиотеки (`libmylib.a`) вы создадите разделяемую библиотеку (`libmylib.so` или `.dll` в зависимости от вашей операционной системы и компилятора) и при компиляции программы вместо флага `-lmylib` вы будете использовать флаг `-lmylib.so` или `-lmylib.dll`, соответственно.

#### Создание динамической библиотеки Набор исходных файлов аналогичен примеру сверху. ```shell gcc -fPIC -c first.cpp gcc -fPIC -c second.cpp gcc -shared -o libhello.so.2.4.0.5 -Wl,-soname,libhello.so.2 first.o second.o ``` `-fPIC` - требует от компилятора, при создании объектных файлов, порождать позиционно-независимый код (PIC - Position Independent Code), его основное отличие в способе представления адресов. Вместо указания фиксированных (статических) позиций, все адреса вычисляются исходя из смещений заданных в глобальной таблицы смещений (global offset table - GOT). Формат позиционно-независимого кода позволяет подключать исполняемые модули к коду основной программы в момент её загрузки. Соответственно, основное назначение позиционно-независимого кода - создание динамических (разделяемых) библиотек. `-shared` - указывает `gcc`, что в результате должен быть собран не исполняемый файл, а «разделяемый объект» - динамическая библиотека. `-Wl` - Обычно, компилятор сам вызывает линковщик и передает ему параметры по своему усмотрению. Этот параметр позволяет передать линковщику опции руками. Общий вид: `gcc -Wl,-option,value1,value2…` что означает передать линковщику (`-Wl`) опцию `-option` с аргументами `value1, value2`. `-soname` - опция линковщика (передаваемая через `-W`) …

надо дописать, но не здесь, а выше

(https://uzverss.livejournal.com/57883.html) #### Подключение динамической библиотеки #недописанное