Компиляция и линковка в C++ для начинающих: от .cpp до .exe с...

Компиляция и линковка в C++ для начинающих: от .cpp до .exe с g++, Clang и MSVC

Компиляция и линковка в C++ для начинающих: от .cpp до .exe с g++, Clang и MSVC

Эта статья — практическое руководство по теме «компиляция и линковка C++». Разберём, что такое объектные файлы, как собрать проект из нескольких .cpp, чем отличаются статические и динамические библиотеки, а также как запускать команды для g++, Clang и MSVC. В конце — типичные ошибки и быстрые способы их починить.

Минимальный пример: два .cpp и заголовок

Создадим крошечную библиотеку суммирования и использующий её main:

// sum.h
#pragma once
int sum(int a, int b);
// sum.cpp
#include "sum.h"
int sum(int a, int b) { return a + b; }
// main.cpp
#include <iostream>
#include "sum.h"
int main() {
    std::cout << sum(2, 3) << "n";
    return 0;
}

Шаг 1. Компиляция в объектные файлы (.o, .obj)

Компилятор переводит каждый .cpp в объектный файл с машинным кодом, но ещё без «склейки» между файлами.

  • g++ или Clang (Linux/macOS/MinGW):
  • g++ -std=c++17 -Wall -Wextra -O2 -c sum.cpp -o build/sum.o
    g++ -std=c++17 -Wall -Wextra -O2 -c main.cpp -o build/main.o
    
  • MSVC (Windows):
  • cl /std:c++17 /EHsc /c sum.cpp /Fobuildsum.obj
    cl /std:c++17 /EHsc /c main.cpp /Fobuildmain.obj
    

    Шаг 2. Линковка: собираем исполняемый файл

    Линкер склеивает объектные файлы и внешние библиотеки в исполняемый файл.

  • g++/Clang:
  • g++ build/main.o build/sum.o -o app
    
  • MSVC:
  • link buildmain.obj buildsum.obj /OUT:app.exe
    // либо одной командой cl:
    cl /std:c++17 /EHsc main.cpp sum.cpp /Fe:app.exe
    

    Статические библиотеки (.a, .lib)

    Статическая библиотека упаковывает объектные файлы. При линковке код копируется в итоговый бинарник (удобно для простого деплоя).

    1. Собираем объектные файлы:
    g++ -c sum.cpp -o build/sum.o
    
    1. Создаём статическую библиотеку:
    ar rcs build/libmymath.a build/sum.o
    
    1. Линкуем с ней приложение:
    g++ -c main.cpp -o build/main.o
    g++ build/main.o -Lbuild -lmymath -o app
    

    На Windows (MSVC) статическая библиотека — .lib:

    cl /c sum.cpp /Fobuildsum.obj
    lib /OUT:buildmymath.lib buildsum.obj
    cl main.cpp buildmymath.lib /Fe:app.exe
    

    Динамические библиотеки (.so, .dll, .dylib)

    Динамическая библиотека подключается во время выполнения. Итоговый бинарник меньше, а библиотеку можно обновлять отдельно.

  • Linux/macOS (GCC/Clang):
  • // создаём общую библиотеку
    g++ -fPIC -shared sum.cpp -o build/libmymath.so
    // линкуем приложение и настраиваем поиск .so рядом с бинарником
    g++ main.cpp -Lbuild -lmymath -Wl,-rpath,'$ORIGIN' -o app
    
  • Windows (MSVC): экспорт/импорт символов через макросы:
  • // mymath.h
    #pragma once
    #ifdef _WIN32
      #ifdef MYMATH_EXPORTS
        #define MYMATH_API __declspec(dllexport)
      #else
        #define MYMATH_API __declspec(dllimport)
      #endif
    #else
      #define MYMATH_API
    #endif
    MYMATH_API int sum(int a, int b);
    
    // mymath.cpp
    #include "mymath.h"
    int sum(int a, int b) { return a + b; }
    
    // сборка DLL и импортной библиотеки
    cl /std:c++17 /EHsc /LD mymath.cpp /FemyMath.dll /DMYMATH_EXPORTS
    // линковка приложения с импортной библиотекой
    cl /std:c++17 /EHsc main.cpp myMath.lib /Fe:app.exe
    

    Для запуска положите myMath.dll рядом с app.exe или пропишите путь в PATH.

    Порядок линковки и поиск библиотек

  • Для GCC/Clang порядок важен: сначала объектные файлы, затем библиотеки: g++ main.o -L. -lmymath.
  • Поиск: -L<путь> добавляет каталог, -l<имя> ищет lib<имя>.so/.a. На Windows с MSVC указывают .lib явно.
  • В runtime: Linux — LD_LIBRARY_PATH или rpath; Windows — рядом с exe или в PATH; macOS — @rpath/@loader_path.
  • Типичные ошибки компиляции и линковки

    1) undefined reference (GCC/Clang) / unresolved external symbol (MSVC)
    Причины: забыли добавить .o/.lib/.a к линковке; несовпадение сигнатур; отключили нужную библиотеку; нарушен extern «C» при линковке с C-библиотекой.
    Как чинить: убедитесь, что все определения присутствуют при линковке; проверяйте порядок для GCC; сигнатуры функций в .h и .cpp совпадают.

    2) multiple definition
    Причины: определили функцию в заголовке без inline; один и тот же объектный файл подключён дважды; дублирующие реализации в разных файлах.
    Как чинить: переносите реализацию в .cpp и оставляйте в .h только объявления; для маленьких функций в .h используйте inline или static (понимая последствия).

    3) DLL не находится в runtime
    Причины: Windows — .dll не рядом с exe и не в PATH; Linux — не настроен rpath или LD_LIBRARY_PATH.
    Как чинить: кладите .dll рядом с .exe; на Linux используйте -Wl,-rpath,'$ORIGIN' или переменную окружения.

    4) Несовместимость ABI
    Причины: линковка библиотек, собранных другим компилятором/стандартной библиотекой C++ или с иными флагами.
    Как чинить: пересобирайте зависимости одним и тем же компилятором и профилем (Debug/Release, C++ стандарт).

    Практические советы

  • Структурируйте проект: include/ для заголовков, src/ для .cpp, build/ для артефактов.
  • Флаги по умолчанию: -Wall -Wextra -Wpedantic (GCC/Clang), в Debug ещё -g; в Release — -O2 -DNDEBUG. Для MSVC: /W4 /Zi в Debug, /O2 /DNDEBUG в Release.
  • Следите за порядком библиотек при линковке в GCC/Clang.
  • Динамические библиотеки делайте с чётким API и версионированием; статические — для простого деплоя без зависимостей на целевой машине.
  • Освойте CMake, когда поймёте основы компиляции и линковки C++ — это облегчит кроссплатформенную сборку.
  • Итоги

    Теперь вы понимаете, как устроены компиляция и линковка C++: объектные файлы, статические и динамические библиотеки, команды для g++/Clang/MSVC, а также типичные ошибки и пути их решения. Следующим шагом может стать освоение систем сборки и углубление в оптимизацию и отладку.

    Хотите быстрее перейти от теории к практике на реальных задачах? Рекомендую изучить программу курса «Программирование на C++ с Нуля до Гуру» — он системно закрывает пробелы и даёт много практики: Прокачать C++ и сборку проектов — посмотреть программу курса.

    Источник

    НЕТ КОММЕНТАРИЕВ

    Оставить комментарий