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

Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Предыдущая версия справа и слеваПредыдущая версия
Следующая версия
Предыдущая версия
soft:gcc [2025/03/18 10:39] – удалено - внешнее изменение (Дата неизвестна) A User Not Logged insoft:gcc [2026/03/03 15:27] (текущий) radi0dev
Строка 1: Строка 1:
 +====== gcc ======
  
 +GCC- GNU Compiler Collection
 +
 +(https://www.opennet.ru/docs/RUS/gcc/)
 +
 +===== Состав компилятора g++ =====
 +
 +''cpp'' — препроцессор\\
 +''as'' — ассемблер\\
 +''g++'' — компилятор\\
 +''ld'' — линкер
 +
 +===== Работа с GCC =====
 +
 +(https://www.opennet.ru/docs/RUS/gcc/gcc1-2.html)
 +
 +==== Общие опции ====
 +
 +<code bash>
 +-Dname=value # Определить имя name в компилируемой программе, как значение value. Эффект такой же, как наличие строки #define name value в начале программы
 +-o filename # Использовать filename в качестве имени для создаваемого файла
 +-Wall # Вывод сообщений о всех предупреждениях или ошибках, возникающих во время компиляции программы
 +</code>
 +
 +==== Остановка на промежуточной стадии ====
 +
 +<code bash>
 +-E # Остановиться после стадии препроцессирования
 +-S # Остановиться после собственно компиляции
 +-c # Компилировать или ассемблировать исходные файлы, но не линковать
 +</code>
 +
 +Компиляция может включать до четырех стадий: препроцессирование, компиляцию, ассемблирование и линковку (всегда в этом порядке). Первые три стадии **применяются к отдельному** исходному файлу и заканчиваются получением объектного файла; линковка **объединяет все** объектные файлы.
 +
 +Для любого имени входного файла суффикс определяет какая компиляция требуется:
 +
 +<code bash>
 +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        # Ассемблерный код, который  нуждается в препроцессировании.
 +другие         # Объектный файл, который нужно отдать прямо на линковку. Так поступают с любым именем файла с нераспознанным суффиксом.
 +
 +</code>
 +Так же язык можно указать явно: ''-x язык''\\
 +Принимаются следующие языки: ''c''; ''objective-c'' ; ''c++'' ; ''c-header'' ; ''cpp-output'' ; ''c++-cpp-output'' ; ''assembler'' ; ''assembler-with-cpp''
 +
 +==== Опции оптимизации ====
 +
 +<code bash>
 +-O0 # Не оптимизировать
 +-O1 # Оптимизировать. Оптимизированная трансляции требует несколько больше времени и несколько больше памяти для больших функций
 +-O2 # Оптимизирует больше. GNU CC выполняет почти все поддерживаемые оптимизации, которые не включают уменьшение времени исполнения за счет увеличения длины кода
 +-O3 # Оптимизирует еще больше. Включает все оптимизации, определяемые -O2, а также включает опцию inline-functions.
 +
 +# Если вы используете многочисленные -O опции с номерами или без номеров уровня, действительной является последняя такая опция.
 +</code>
 +
 +==== Опции управления зависимостями ====
 +
 +<code bash>
 +-lfoo # Использовать при компоновке динамическую библиотеку foo.so
 +# аналогично для статической библиотеки foo.a
 +-l:foo.so # Аналогично, но через двоеточие можно указать полное имя библиотеки
 +-Llibpath # Добавить к стандартным каталогам поиска библиотек путь libpath
 +-Iincludepath # Добавить к стандартным каталогам поиска заголовочных файлов путь includepath
 +</code>
 +
 +Опция ''-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):
 +
 +<code bash>
 +g++ hello.cpp -o prog
 +</code>
 +
 +Дополнительный необязательный параметр ''-o prog'' указывает, что скомпилированный файл будет называться prog.exe. Если не указать этот параметр, то файл будет называться по умолчанию - a.exe.
 +
 +==== Отдельная компиляция ====
 +
 +C++ допускает раздельную компиляцию, а это означает, что каждый исходный файл может быть независимо скомпилирован в объектный файл. Эти объектные файлы затем можно соединить вместе, чтобы сформировать окончательный исполняемый файл. Это обеспечивает более быстрое время сборки при внесении изменений в один исходный файл, поскольку необходимо перекомпилировать только этот файл, а другие объектные файлы можно использовать повторно.
 +
 +Пример раздельной компиляции и компоновки:
 +
 +<code bash>
 +# Скомпилируем исходные файы в объектные файлы
 +g++ -c main.cpp -o main.o
 +g++ -c funcs.cpp -o funcs.o
 +
 +# Линкуем объектные файлы вместе, чтобы создать исполняемый файл
 +g++ main.o funcs.o -o my_program
 +</code>
 +
 +==== Создание статической библиотеки ====
 +
 +Допустим, у нас есть исходники с реализациями функций ''first.cpp'', ''second.cpp'' и заголовочник ''libmy.h'' с объявлением ф-ий из исходников. Скомпилируем и заархивируем:
 +
 +<code bash>
 +# компилируем
 +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
 +</code>
 +
 +архиватор ar - утилита "склеивает" несколько файлов в один, не сжимая их содержимое.\\
 +''-c <filename>'': создать архив, если архив с именем "filename" не существует он будет создан, в противном случае файлы будут добавлены к имеющемуся архиву.\\
 +''-r'': Pадает режим обновления архива, если в архиве файл с указанным именем уже существует, он будет удален, а новый файл дописан в конец архива.\\
 +''-s'': Добавляет (обновляет) индекс архива. В данном случае индекс архива это таблица, в которой для каждого определенного в архивируемых файлах символического имени (имени функции или блока данных) сопоставлено соответствующее ему имя объектного файла. Индекс архива необходим для ускорения работы с библиотекой - для того чтобы найти нужное определение, отпадает необходимость просматривать таблицы символов всех файлов архива, можно сразу перейти к файлу, содержащему искомое имя. Просмотреть индекс архива можно с помощью уже знакомой утилиты nm воспользовавшись её опцией ''-s''.
 +
 +Для создания индекса архива существует специальная утилита ranlib. Библиотеку libmy.a можно было сотворить и так:
 +
 +<code bash>
 +ar cr libmy.a first.o second.o  
 +ranlib libmy.a
 +</code>
 +
 +Впрочем библиотека будет прекрасно работать и без индекса архива.
 +
 +=== Подключение статической библиотеки ===
 +
 +Допустим, у нас есть файл ''main.cpp'' , содержащий ''#include "libmy.h"''. Соберём (компиляция+линковка) программу:
 +
 +<code bash>
 +gcc -Wall -c main.c # компиляция программы
 +gcc -o mainprog main.o -L. -llibmy # линковка программы вместе с архивом с реализациями функций
 +</code>
 +
 +Повторю:\\
 +''-L/путь/к/каталогу/с/библиотеками'' указывает путь к каталогу содержащему подключаемые библиотеки.\\
 +''-l<name>'' имя библиотеки задается как "name" без приставки "lib" 
 +
 +Компиляция либы:
 +<code cpp>
 +// компиляция lib.cpp в объектный файл
 +g++ -c lib.cpp -o lib.o
 +// архивируем в статическую библиотеку
 +ar rcs libmylib.a lib.o
 +</code>
 +
 +Использование либы:
 +<code cpp>
 +// компилим файл main с подключением либы
 +g++ main.cpp -o prog -L. -lmylib
 +</code>
 +Здесь:
 +- ''-L .'' указывает компилятору искать библиотеку в текущем каталоге.
 +- ''-lmylib'' говорит компилятору использовать библиотеку ''libmylib.a''.
 +
 +Эти шаги создадут исполняемый файл ''prog'', содержащий код из ''main.cpp'', а также функции из вашей статической библиотеки ''libmylib.a''.
 +
 +Если вы хотите создать динамическую библиотеку, то процесс будет немного отличаться. Для этого вместо создания статической библиотеки (''libmylib.a'') вы создадите разделяемую библиотеку (''libmylib.so'' или ''.dll'' в зависимости от вашей операционной системы и компилятора) и при компиляции программы вместо флага ''-lmylib'' вы будете использовать флаг ''-lmylib.so'' или ''-lmylib.dll'', соответственно.
 +
 +
 +==== Создание динамической библиотеки ====
 +
 +Набор исходных файлов аналогичен примеру сверху.
 +
 +<code bash>
 +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
 +</code>
 +
 +''-fPIC'' - требует от компилятора, при создании объектных файлов, порождать позиционно-независимый код (PIC - Position Independent Code), его основное отличие в способе представления адресов. Вместо указания фиксированных (статических) позиций, все адреса вычисляются исходя из смещений заданных в глобальной таблицы смещений (**g**lobal **o**ffset **t**able - GOT). Формат позиционно-независимого кода позволяет подключать исполняемые модули к коду основной программы в момент её загрузки. Соответственно, основное назначение позиционно-независимого кода - создание динамических (разделяемых) библиотек.\\
 +''-shared'' - указывает ''gcc'', что в результате должен быть собран не исполняемый файл, а "разделяемый объект" - динамическая библиотека.\\
 +''-Wl'' - Обычно, компилятор сам вызывает линковщик и передает ему параметры по своему усмотрению. Этот параметр позволяет передать линковщику опции руками. Общий вид: ''gcc -Wl,-option,value1,value2...'' что означает передать линковщику (''-Wl'') опцию ''-option'' с аргументами ''value1, value2''.\\
 +''-soname'' - опция линковщика (передаваемая через ''-W'') {{fixme}}
 +
 +([[https://uzverss.livejournal.com/57883.html]])
 +=== Подключение динамической библиотеки ===
 +{{fixme}}