КАК ФАЙЛЫ СТАНОВЯТСЯ ПРОГРАММОЙ
Прежде чем доверять сборку инструментам, полезно понять, что именно они делают: четыре стадии трансляции, единицы трансляции, заголовки и правила связывания.
Единица трансляции
Компилятор не видит «проект». Он видит одну единицу трансляции (ТУ) — файл .cpp после раскрытия всех #include. Каждый .cpp компилируется независимо, а результаты сшивает линковщик.
parser.cpp
#include "parser.h"
#include <vector>
…определения функций…
Препроцессор
вставляет содержимое заголовков, раскрывает макросы, выполняет #ifdef
parser.i → parser.o
чистый текст → объектный файл с машинным кодом и таблицей символов
Четыре стадии — вручную
Препроцессинг
Текстовая подготовка: включения, макросы, условная компиляция.
Компиляция
Перевод в ассемблер: синтаксис, шаблоны, перегрузки, оптимизации.
Ассемблирование
Инструкции становятся машинным кодом, появляется таблица символов.
Линковка
Объекты и библиотеки соединяются: символы получают адреса.
Ключ -c — самый важный для систем сборки: он останавливается после ассемблирования и даёт объектный файл, который можно переиспользовать, кэшировать и линковать отдельно.
Заголовки и стражи включения
#ifndef ENGINE_H
#define ENGINE_H
namespace engine {
class Engine {
public:
void start(int rpm);
};
}
#endif // ENGINE_H
#pragma once
namespace engine {
class Engine; // forward declaration
void tune(Engine& e);
}
Правило скорости: чем меньше заголовков тянет заголовок — тем быстрее сборка. Вперёд-объявляйте классы, включайте только то, что реально используете.
ODR и связывание
One Definition Rule: у каждого символа должно быть ровно одно определение на программу (для inline — сколько угодно одинаковых).
| extern | объявление без определения: символ живёт в другой единице трансляции и будет найден при линковке |
| static в .cpp | внутреннее связывание: функция или переменная видна только внутри своего файла |
| inline | определение может повторяться в разных ТУ — линковщик оставит одну копию |
| const / constexpr | переменные по умолчанию имеют внутреннее связывание — в каждом .cpp своя копия |