C++ везде: как писать код для Windows, Linux и macOS сразу

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Однажды ты напишешь код, который запустится везде

Представь: ты создаёшь крутой проект на C++, всё работает идеально под Windows. Твой друг просит собрать версию для Linux. Ты вздыхаешь, лезешь в Makefile, меняешь пути, компиляторы, натыкаешься на #ifdef _WIN32 и через три часа получаешь бинарник, который всё равно падает с segmentation fault. Знакомо?

Кроссплатформенная разработка на C++ — это не магия, а набор дисциплин и инструментов. В этой статье мы разберём, как писать код, который работает на Windows, Linux и macOS без слёз, с примерами реального кода и готовыми решениями. Погнали!

Почему C++ идеален для кроссплатформенности (и почему это боль)

Сильные стороны C++ — компилируемость, производительность и контроль над памятью — делают его королём системного программирования. Но за это приходится платить: каждая ОС имеет свои API, компиляторы (MSVC, GCC, Clang) и особенности файловой системы.

Основные грабли:

  • Разные заголовочные файлы — windows.h vs unistd.h
  • Разные макросы — _WIN32, __linux__, __APPLE__
  • Разные компиляторы — MSVC не любит GCC-расширения
  • Разные библиотеки — динамическая загрузка (DLL vs .so)

Но не бойся — все эти проблемы решаемы. Главное — выбрать правильный подход с самого начала.

Инструмент №1: CMake — твой универсальный сборщик

Если ты пишешь кроссплатформенное приложение на C++, твой лучший друг — CMake. Это не система сборки вроде Make, а генератор файлов сборки: он создаёт Makefile для Linux/macOS и .sln для Visual Studio под Windows.

Вот минимальный CMakeLists.txt, который работает везде:

cmake_minimum_required(VERSION 3.16)
project(CrossPlatformApp VERSION 1.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Добавляем исполняемый файл
add_executable(myapp main.cpp utils.cpp)

# Кроссплатформенная обработка
if(WIN32)
    target_compile_definitions(myapp PRIVATE PLATFORM_WINDOWS)
    target_link_libraries(myapp PRIVATE ws2_32)  # сокеты под Windows
elseif(APPLE)
    target_compile_definitions(myapp PRIVATE PLATFORM_MACOS)
    target_link_libraries(myapp PRIVATE "-framework CoreFoundation")
else()
    target_compile_definitions(myapp PRIVATE PLATFORM_LINUX)
endif()

Как видишь, target_compile_definitions позволяет задавать макросы для каждой платформы. В коде ты используешь их так:

#ifdef PLATFORM_WINDOWS
    #include <windows.h>
    void sleep_ms(int ms) { Sleep(ms); }
#else
    #include <unistd.h>
    void sleep_ms(int ms) { usleep(ms * 1000); }
#endif

CMake — стандарт де-факто. Если твой проект его не использует, пора менять подход.

Boost и Qt: готовые решения для сложных задач

Писать всё с нуля — удел героев и мазохистов. Для кроссплатформенной разработки на C++ существуют зрелые библиотеки, которые скрывают различия ОС.

Boost — швейцарский нож

Boost.Asio — для сетевого программирования (работает и на Windows, и на Linux). Boost.Filesystem — для работы с файлами (заменит std::filesystem, если у тебя старый компилятор). Пример кроссплатформенного чтения директории:

#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;

void list_files(const std::string& path) {
    for (const auto& entry : fs::directory_iterator(path)) {
        std::cout << entry.path().string() << std::endl;
    }
}

Этот код соберётся под любой ОС без единого #ifdef.

Qt — полноценный фреймворк

Если тебе нужен GUI, работа с сетью, базами данных или многопоточность — Qt твой выбор. Он даёт единый API для всех платформ. Пример простого окна:

#include <QApplication>
#include <QLabel>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QLabel label("Привет, кроссплатформенность!");
    label.show();
    return app.exec();
}

Qt компилируется под Windows, Linux, macOS, Android и iOS. Для образовательных проектов на PythonLib это отличный пример, как C++ может быть переносимым.

Написание переносимого кода: практические советы

Кроссплатформенное программирование на C++ — это не только выбор библиотек, но и стиль кода. Вот конкретные рекомендации:

1. Используй стандартную библиотеку

std::thread, std::filesystem, std::string — это переносимо. Избегай прямых системных вызовов, если есть стандартная альтернатива.

2. Не полагайся на размер типов

int может быть 2 или 4 байта. Используй int32_t, uint64_t из <cstdint>.

3. Разделяй логику и платформу

Выноси платформозависимый код в отдельные файлы: network_win.cpp, network_unix.cpp. В CMake подключай нужный:

if(WIN32)
    target_sources(myapp PRIVATE network_win.cpp)
else()
    target_sources(myapp PRIVATE network_unix.cpp)
endif()

4. Обрабатывай пути к файлам

На Windows путь — C:\Users\user\file.txt, на Linux — /home/user/file.txt. Используй std::filesystem::path или Boost.Filesystem. Не пиши вручную слеши!

#include <filesystem>
namespace fs = std::filesystem;

fs::path home = fs::path(getenv("HOME")) / "project" / "data.txt";
// Под Windows сработает корректно, если заменить getenv на свою обёртку

Реальный пример: кроссплатформенный HTTP-клиент

Давай соберём всё вместе. Напишем простой HTTP-клиент, который работает на Windows и Linux. Используем Boost.Asio и немного макросов для инициализации сокетов.

Файл http_client.cpp

Блоги

Рекомендаций по книгам